Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does adding an as-pattern to a working function cause compilation errors?

Here's the standard Functor instance for Either a:

instance Functor (Either a) where
        fmap _ (Left x) = Left x
        fmap f (Right y) = Right (f y)

adding in an as-pattern causes compilation errors when loading into GHCi:

instance Functor (Either a) where
        fmap _ z@(Left x) = z          -- <-- here's the as-pattern
        fmap f (Right y) = Right (f y)

Couldn't match expected type `b' against inferred type `a1'
  `b' is a rigid type variable bound by
      the type signature for `fmap' at <no location info>
  `a1' is a rigid type variable bound by
       the type signature for `fmap' at <no location info>
  Expected type: Either a b
  Inferred type: Either a a1
In the expression: z
In the definition of `fmap': fmap _ (z@(Left x)) = z

Why doesn't this work?

like image 648
Matt Fenwick Avatar asked Aug 21 '12 13:08

Matt Fenwick


2 Answers

fmap has signature (a -> b) -> f a -> f b, i.e. it has to allow for a and b to be different. In your implementation, a and b can only be the same, because it returns the same thing that was passed as an argument. So GHC complains.

like image 187
Cat Plus Plus Avatar answered Oct 29 '22 20:10

Cat Plus Plus


My best guess is that this fails because z represents different types on each side of the equation:

  • the overall type is fmap :: (a -> b) -> Either t a -> Either t b

  • on the left side, z :: Either t a

  • on the right side, z :: Either t b

It seems that Left x is allowed to have multiple different types in the same equation, but z is not.

This implementation also fails, apparently for the same reason:

instance Functor (Either a) where
        fmap f (Right y) = Right (f y)
        fmap _ z = z          

Couldn't match expected type `b' against inferred type `a1'
  `b' is a rigid type variable bound by
      the type signature for `fmap' at <no location info>
  `a1' is a rigid type variable bound by
       the type signature for `fmap' at <no location info>
  Expected type: Either a b
  Inferred type: Either a a1
In the expression: z
In the definition of `fmap': fmap _ z = z
like image 36
Matt Fenwick Avatar answered Oct 29 '22 19:10

Matt Fenwick