Published on February 12, 2015
The Foldable-Traversable proposal (aka FTP) has spawned a lot of debate in the Haskell community.
Here I want to analyze the specific concern which Ben Moseley raised in his post, FTP dangers.
Ben’s general point is that more polymorphic (specifically, ad-hoc polymorphic, i.e. using type classes) functions are less readable and reliable than their monomorphic counterparts.
On the other hand, Tony Morris and Chris Allen argue on twitter that polymorphic functions are more readable due to parametricity.
Is that true, however? Are the ad-hoc generalized functions more parametric than the monomorphic versions?
@shebang @dibblego is— Je Suis Petit Gâteau (@bitemyapp) February 12, 2015
(a -> b) -> [a] -> [b]more parametric than
Functor f => (a -> b) -> f a -> f b?
Technically, the Functor-based type is more parametric. A function with type
(a -> b) -> [a] -> [b] is something like
map, except it may drop or duplicate some elements. On the other hand,
Functor f => (a -> b) -> f a -> f b has to be
But this is a trick question! The first thing we see in the code is the function’s name, not its type. What carries more information,
fmap? (Assuming both come from the current Prelude.) Certainly
fmap is instantiated at the list type, it is nothing more than
map. When we see
fmap, we know that it may or may not be
map. When we see
map, we know it is
map and nothing else.
The paradox is that there are more functions with
map’s type than
fmap’s, but there are more functions with
fmap’s name than
map’s. Even though
fmap is more parametric, that doesn’t win us much.
Nevertheless, is there a benefit in using more parametric functions in your code? No. If it were true, we’d all be pumping our code with «parametricity» by writing
id 3 instead of
3. You can’t get more parametric than
Merely using parametric functions doesn’t make code better. Parametricity may pay off when we’re defining polymorphic parametric functions in our code instead of their monomorphic instantiations, since parametric types are more constrained and we’re more likely to get a compile error should we do anything stupid.
(It won’t necessarily pay off; the type variables and constraints do impose a tax on types’ readability.)
But if you have an existing, monomorphic piece of code that works with lists, simply replacing
Data.List functions with
Data.Foldable ones inside it, ceteris paribus, will not make your code any safer or more readable.