I'm trying to figure out what exactly are the rules for deriving Functor
in Haskell.
I've seen message postings about it, and I've seen test code about it, but I can't seem to find official documentation about what the rules are. Can someone please clarify and/or point me to the right place?
Deriving means that your data type is automatically able to "derive" instances for certain type classes. In this case BaseballPlayer derives Show which means we can use any function that requires an instance of Show to work with BaseballPlayer .
String is not a functor, because it has the wrong kind.
To use deriving Functor you must enable the DeriveFunctor language pragma and apply it to a polymorphic type which has a covariant final type variable---in other words, a type which admits a valid Functor instance. It'll then derive the "obvious" Functor instance.
DeriveFunctor was first introduced in GHC 6.12, but the release notes for it don't provide any additional clues. To use deriving Functor you must enable the DeriveFunctor language pragma and apply it to a polymorphic type which has a covariant final type variable---in other words, a type which admits a valid Functor instance.
Can someone please clarify and/or point me to the right place? DeriveFunctor was first introduced in GHC 6.12, but the release notes for it don't provide any additional clues.
To use deriving Functor
you must enable the DeriveFunctor
language pragma and apply it to a polymorphic type which has a covariant final type variable---in other words, a type which admits a valid Functor
instance. It'll then derive the "obvious" Functor
instance.
There's been some concern in the past that the derived instance is not as efficient as a hand coded one is, though I cannot seem to find that material.
The algorithm itself was, as far as I could find, first proposed by Twan Van Laarhoven in 2007 and makes heavy use of Generic Haskell programming.
The code that actually does the deed is, unfortunately, a bit on the hairy side. I believe that's largely because earlier, simpler code would sometimes lead to excessive compilation times. Twan van Laarhoven came up with the current code to address this.
The derived Functor
instance always does the obvious thing. This is usually just fine, but occasionally misses opportunities. For example, suppose I write
data Pair a = Pair a a deriving Functor data Digit a = One a | Two a a deriving Functor data Queue a = Empty | Single a | Deep !(Digit a) (Queue (Pair a)) !(Digit a) deriving Functor
This will generate (in GHC 8.2)
instance Functor Queue where fmap ... x <$ Empty = Empty x <$ Single y = Single x x <$ Deep pr m sf = Deep (x <$ pr) (fmap (x <$) m) (x <$ sf)
It's possible to write that last case much better by hand:
x <$ Deep pr m sf = Deep (x <$ pr) (Pair x x <$ m) (x <$ sf)
You can see the actual derived code using -ddump-deriv
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With