Consider the following transcript of GHCi, version 8.2.2:
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
Prelude> :set -XRankNTypes
Prelude> data Functor f = Functor { fmap :: forall a b. (a -> b) -> f a -> f b }
Prelude> :t fmap
fmap :: Functor f1 -> (a -> b) -> f2 a -> f2 b
Prelude> :t Functor map
Functor map :: Functor []
Prelude> :t fmap (Functor map)
fmap (Functor map) :: (a -> b) -> [a] -> [b]
As you can see, the type of fmap
is inferred as Functor f1 -> (a -> b) -> f2 a -> f2 b
. This is surprising because f1
and f2
are supposed to be the same type variable but there's no f1 ~ f2
constraint. Nevertheless, if you apply fmap
to Functor map
which has the type Functor []
, the result still has the type (a -> b) -> [a] -> [b]
as expected. What's going on here? I would have expected fmap
to have the type Functor f -> (a -> b) -> f a -> f b
.
I can confirm that this issue affects GHC 8.2.2 but not 8.0.2. Update: It looks like it's been fixed on the 8.4 branch.
It appears to be a GHCi type signature display bug, rather than a real type checker issue, since if you take the program:
{-# LANGUAGE RankNTypes #-}
module Inference where
data Functor f = Functor { fmap :: forall a b. (a -> b) -> f a -> f b }
and compile it with ghc -ddump-tc
, you can see that GHC infers the correct type:
TYPE SIGNATURES
...
Inference.fmap ::
forall (f :: * -> *).
Inference.Functor f -> forall a b. (a -> b) -> f a -> f b
It also doesn't seem to affect GHC error messages. If you add the line:
main = print Inference.fmap
to produce an error message that includes the type ("No instance for (Show xxx)"), you also see the correct type.
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