Named patterns and output type?

I worked with some examples and encountered an error with my implementation of bind (→ =) for Monad error:

data E a = Success a
         | Error String

instance Monad E where
    return a = Success a
    (Success a) >>= f = f a
    e@(Error s) >>= _ = e

 

Error.hs:15:25:
Couldn't match type `a' with `b'
  `a' is a rigid type variable bound by
      the type signature for >>= :: E a -> (a -> E b) -> E b
      at Error.hs:14:5
  `b' is a rigid type variable bound by
      the type signature for >>= :: E a -> (a -> E b) -> E b
      at Error.hs:14:5
Expected type: E b
  Actual type: E a
In the expression: e
In an equation for `>>=': e@(Error s) >>= _ = e
In the instance declaration for `Monad E'

If you do not use a named template (syntax @), everything works:

(Error s) >>= _ = Error s

Why are these two forms not equivalent? What's happening?

+4
source share
1 answer

Let's start by looking at the type Error:

Error :: String -> E a

This means that for any type, ayou can get E ausing something like Error "foo". However, each specific value Error "foo"must choose a specific one a, and subsequently you cannot change it. So Error "foo" :: E Intdoes not match with Error "foo" :: E String.

, e "" Error s E a, Error s, E b.

+12

Source: https://habr.com/ru/post/1540142/


All Articles