kjo
kjo

Reputation: 35311

On a Functor instance declaration

This loads without error:

data Const c a = Const c

instance Functor (Const c) where
    fmap _ (Const v) = Const v

...but this

data Const' c a = Const' c

instance Functor (Const' c) where
    fmap _ cv = cv

...fails with:

    Couldn't match type `a' with `b'
      `a' is a rigid type variable bound by
          the type signature for fmap :: (a -> b) -> Const' c a -> Const' c b
          at test.hs:4:5
      `b' is a rigid type variable bound by
          the type signature for fmap :: (a -> b) -> Const' c a -> Const' c b
          at test.hs:4:5
    Expected type: Const' c b
      Actual type: Const' c a
    In the expression: cv
    In an equation for `fmap': fmap _ cv = cv
    In the instance declaration for `Functor (Const' c)'

I don't understand the error. Why can't the compiler infer that the type of cv is Const' c? What else could it be, given the rest of the declaration, and the definition of fmap?

Upvotes: 7

Views: 272

Answers (2)

Rein Henrichs
Rein Henrichs

Reputation: 15605

cv is of type Const' c a, so it can't also be of type Const' c b (unless a ~ b). Const v and Const v, however, can be of different types.

Another way of looking at it is that fmap _ cv = cv is equivalent to fmap _ = id, which would be of type Const' c a -> Const' c a, but fmap _ must be of type Const' c a -> Const' c b.

Upvotes: 7

luqui
luqui

Reputation: 60463

If you want to be fully explicit, you can write

{-# LANGUAGE ScopedTypeVariables, InstanceSigs #-}

data Const c a = Const c

instance Functor (Const c) where
    fmap :: forall a b. (a -> b) -> Const c a -> Const c b
    fmap _ (Const v :: Const c a) = Const v :: Const c b

Which is a bit of a mouthful. :-)

forall a b. brings a and b into scope so they can be referred to in the definition. This is enabled by ScopedTypeVariables. InstanceSigs allows us to write the signature of fmap in the first place (normally it must be inferred from the class, so we have nowhere to get the type variable names from).

Upvotes: 9

Related Questions