命名模式和类型推断?

时间:2014-05-11 21:02:24

标签: haskell

我正在处理一些示例,并且遇到错误monad的bind(>> =)实现错误:

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'

如果不使用命名模式(@语法),一切正常:

(Error s) >>= _ = Error s

为什么这两种形式不相同?发生了什么事?

1 个答案:

答案 0 :(得分:12)

让我们先看一下Error的类型:

Error :: String -> E a

这意味着,对于任何a类型,您都可以使用E a之类的内容获得Error "foo"。但是,每个特定Error "foo"值都必须选择特定的a,之后您无法更改它。因此Error "foo" :: E IntError "foo" :: E String不同。

因此,在您的具体示例中,e指的是Error s类型的实际“原始”E a值,而在替代公式中,您构建的是 new Error s值,类型推断强制使用类型E b

相关问题