我目前正在逐步阅读论文 Monad Transformers 由MartinGrabmüller。
论文的一部分列出了以下实例声明:
instance (MonadError e m) => MonadError e (ReaderT r m) where...
我已经看了很多遍,但是我找不到关于(Foo a b)
之类的多参数约束的确切含义的任何信息。我不完全了解e
和m
在实例头=> MonadError e (ReaderT r m)
中如何一起工作。
这些多参数约束如何起作用?谢谢!
答案 0 :(得分:3)
本质上,像Show a
这样的约束将类型变量a
约束为表示可显示的类型。您似乎明白这一点。
格式为C a b
的约束约束一对类型变量a
和b
。从直觉上讲,这种约束意味着这些类型之间存在联系。
考虑这个虚构类
class C a b where
sum :: a -> b -> (Int, b)
直觉上,约束C a b
意味着a
和b
可以sum
并在一起(按此顺序!),并且总和的结果为对(Int, b)
。
您要处理的问题
class Monad m => MonadError e m | m -> e where
throwError :: e -> m a
在这里,MonadError e m
表示e
和m
之间的以下关系。
m
是一个monad e
是一种类型,对于任何x :: e
,我们都可以将其值throwError x :: m a
转换为a
。直观地讲,这是一种“错误”类型,代表某种错误的性质,throwError
只是在monad中包含了这样的值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)