newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
instance (Monad m, Error e) => Monad (ErrorT e m) where
m >>= k = ErrorT $ do
a <- runErrorT m
case a of
Left l -> return (Left l)
Right r -> runErrorT (k r)
ErrorT
只是一个值构造函数(类型构造函数)并且要获取该类型的实例(获取ErrorT
值)我们必须使用一个参数调用构造函数 - 一个函数(析构函数)得到ErrorT
并返回内部monad,在我们的例子中它是任何m
(Either)。因此,在绑定函数中,它被定义为:m >>= k = ErrorT $ ...
。但是,在其定义中它称为runErrorT
,它只是被定义。所以就像递归调用一样。但是,我想这里没有递归。这意味着我误解了monad / monad变形金刚的一些东西。请帮助:)
答案 0 :(得分:3)
我认为您对newtype
包装器感到困惑。 ErrorT
的newtype定义导致定义了两个函数:
ErrorT :: m (Either e a) -> ErrorT e m a
runErrorT :: ErrorT e m a -> m (Either e a)
所以在(>>=)
的定义中,ErrorT $ do ...
指的是ErrorT
newtype的构造函数,而
a <- runErrorT m
runErrorT (k r)
参考&#39;展开&#39;用于提取基础m (Either e a)
。