Haskell中的多参数上下文约束

时间:2018-11-10 18:46:27

标签: haskell typeclass

我目前正在逐步阅读论文 Monad Transformers 由MartinGrabmüller。

论文的一部分列出了以下实例声明:

instance (MonadError e m) => MonadError e (ReaderT r m) where...

我已经看了很多遍,但是我找不到关于(Foo a b)之类的多参数约束的确切含义的任何信息。我不完全了解em在实例头=> MonadError e (ReaderT r m)中如何一起工作。

这些多参数约束如何起作用?谢谢!

1 个答案:

答案 0 :(得分:3)

本质上,像Show a这样的约束将类型变量a约束为表示可显示的类型。您似乎明白这一点。

格式为C a b的约束约束一对类型变量ab。从直觉上讲,这种约束意味着这些类型之间存在联系。

考虑这个虚构类

class C a b where
   sum :: a -> b -> (Int, b)

直觉上,约束C a b意味着ab可以sum并在一起(按此顺序!),并且总和的结果为对(Int, b)

您要处理的问题

class Monad m => MonadError e m | m -> e where
   throwError :: e -> m a

在这里,MonadError e m表示em之间的以下关系。

  1. m是一个monad
  2. e是一种类型,对于任何x :: e,我们都可以将其值throwError x :: m a转换为a。直观地讲,这是一种“错误”类型,代表某种错误的性质,throwError只是在monad中包含了这样的值
  3. 鉴于m,只有一种错误类型e。换句话说,该关系实际上是一个函数。这是通过上面的类中的功能依赖项... | m -> e来表示的。

简单的版本是:MonadError m a表示m是可以表示类型e的某些“错误值”的单子。

例如,如果我们有MonadError M String可用,我们可以写

foo :: Int -> M Int
foo n | n == 0    = throwError "can't handle zero!"
      | otherwise = return (100 `div` n)