In Haskell Programming From First Principles section 16.13, the Wrap datatype is presented to demonstrate a type whose Functor instance requires a typeclass constraint on one of its parameters:
data Wrap f a =
Wrap (f a)
deriving (Eq, Show)
After demonstrating a couple of incorrect instances of Functor for (Wrap f), a correct instance is shown:
instance Functor f => Functor (Wrap f) where
fmap g (Wrap fa) = Wrap (fmap g fa)
The fact that this typeclass instance should work seems right to me. Indeed, GHC accepts it without complaint.
In order to convince myself that the 'Functor f' constraint is required, I attempted to create my own typeclass instance without it. My approach focuses on pattern matching to use f in a "functor-ish" way without fmap, similar to approaches shown earlier in the book. Here is the attempt:
instance Functor (Wrap f) where
fmap g (Wrap (f a)) = Wrap f (g a)
When I load this into GHCi, I get the following error:
Prelude> :l 16.12-wrap.hs
[1 of 1] Compiling Main ( 16.12-wrap.hs, interpreted )
16.12-wrap.hs:10:17: error: Parse error in pattern: f
|
10 | fmap g (Wrap (f a)) = Wrap f (g a)
| ^^^
Failed, no modules loaded.
Can someone explain the issue with my attempted instance? It seems to me that GHC has enough information to infer that f is of kind (* -> *) from the definition of Wrap at the top, so I can't understand why my attempt does not parse.
fmap g (Wrap (f a)) =
. In particular,f a
is not a valid pattern. I don't really understand what you're trying to express there. – dfeuerfmap g (Wrap (f a))
,f
is not a type (nor a type constructor). – duplodef
in the instance declaration,instance Functor f => Functor (Wrap f)
, is a type constructor. Thef
in thefmap
definition, however, is not the same thing, and not a type constructor. Patterns match values, not types. – duplode