Reputation: 41939
Given the following algebraic type:
ghci> data Foo a = Foo a
Then I instantiate one of them.
ghci> let f = Foo "foo"
Lastly, I'd like to call fmap
to apply a function as, (a -> b) -> Foo a -> Foo b
.
ghci> fmap (++ "bar") f
<interactive>:78:1:
No instance for (Functor Foo) arising from a use of ‘fmap’
In the expression: fmap (++ "bar") f
In an equation for ‘it’: it = fmap (++ "bar") f
But, since I didn't implement a Functor
instance of Foo
, I can't use fmap
.
Is there a way to get Functor
instances for free? I have zero knowledge of Haskell's compiler, but perhaps it's clever enough to know that fmap
on Foo a
is simply apply (a -> b)
to Foo
's a
?
Upvotes: 3
Views: 218
Reputation: 43393
Working in ghci, if you make the incantation
Prelude> :set -XDeriveFunctor
then the compiler will become as clever as you are hoping for, if not quite as enthusiastic. You will need to invoke the functionality, thus,
Prelude> data Foo a = Foo a deriving (Show, Functor)
(the Show
is just for printing the output, below) and then you will be able to do stuff like
Prelude> fmap (++"bar") (Foo "foo")
Foo "foobar"
In a module, you achieve the same by adding the pragma
{-# LANGUAGE DeriveFunctor #-}
before the module
declaration. It's good for at least the more straightforward Functor
instances, but you can fool it into a false negative.
Prelude> data Boo a = Boo (Either a Bool) deriving Functor
<interactive>:9:43:
Can't make a derived instance of ‘Functor Boo’:
Constructor ‘Boo’ must use the type variable only as the
last argument of a data type
In the data declaration for ‘Boo’
Meanwhile
data Goo a = Goo (Either Bool a) deriving Functor
is ok, and the machinery has clearly been hacked to work with pairing, as
data Woo a = Woo (a, Bool) deriving Functor
is permitted.
So it's not as clever as it could be, but it's better than a poke in the eye.
Upvotes: 10
Reputation: 34411
Sure it can, add deriving Functor
to your data declaration and {-# LANGUAGE DeriveFunctor #-}
at the top of file.
Upvotes: 4