Background: I’m investigating anonymous recursion, and I’m taking on the challenge of implementing the prelude without using any named recursion just to help it all sit nicely in my mind. I’m not quite there yet, and along the way I’ve run into something unrelated but still interesting.
map1 = \f -> \x -> if (tail x) == []
then [f (head x)]
else f (head x) : (map1 f (tail x))
map2 f x = if (tail x) == []
then [f (head x)]
else f (head x) : (map2 f (tail x))
map3 f (x:xs) = if xs == [] then [f x] else f x : (map3 f xs)
map4 f (x:[]) = [f x]
map4 f (x:xs) = f x : map4 f xs
GHC complains about the first one, is fine with the second and the third and fourth ones are there just to show how they could be implemented differently.
*Main> map1 (*2) [1..10]
<interactive>:1:15:
No instance for (Num ())
arising from the literal `10'
Possible fix: add an instance declaration for (Num ())
In the expression: 10
In the second argument of `map1', namely `[1 .. 10]'
In the expression: map1 (* 2) [1 .. 10]
*Main> map2 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map3 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map4 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
If I add a type signature to map1 it’s all good.
map1 :: Eq a => (a -> b) -> [a] -> [b]
The first two functions seem pretty much the same to me, so I suppose my question is simply “What’s going on here?”
You were bitten by the monomorphism restriction. Anything that is written as
foo = ...– meaning that there are no arguments to the definition, and no explicit type is given – has to have a non-generic type according to this restriction. The generic type in this case would, as you said, have had to beEq a => (a -> b) -> [a] -> [b], but since the monomorphism restriction applies, bothaandbare replaced by(), the simplest type that can be inferred for the available type variables.