I have the following code:
class Coll c e where
map :: (e1 -> e2) -> c e1 -> c e2
merge :: (e -> e -> e) -> e -> c e -> e
sum :: (Num e) => c e -> e
sum = merge (+) 0
So far so good. But then I have:
sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
sumMap f c = (merge (+) 0) (map f c)
Compiling gives an error:
Could not deduce (Coll c e2) arising from a use a 'merge' from the context (Coll c e) [...] Possible fix: add (Coll c e2) to the context of the type signature for sumMap [...]
So I replace sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
with sumMap :: (Num e2, Coll c e2) => (e1 -> e2) -> c e1 -> e2
, but then it gives another error:
Could not deduce (Coll c e0) arising from a use of 'map' from the context (Coll c e) [...] Possible fix: add a type signature that fixes these type variable(s) [...]
I'm confused, so I comment out the definition for sumMap
, and run :t (merge (+) 0) . (map (* 2))
, which gives me [...] :: (Num c, Coll c1 c, Coll c1 e) => c1 c -> c
. Ignoring how it mangled my variables' names, Coll c1 e
is bizarre; e
is not even used in the definition!, so why is it there!? Anyways, then I run ((merge (+) 0) . (map (* 2))) [1,2,3,4]
, which successfully returns 20
. What's going on here? Why does this function work only when I don't try to tie it to a name?
Foldable
is disguise. – user2407038