我已经定义了我自己的WriterT版本以及一个解包它的函数:
newtype WT w m a = WT (m a, w)
unWT :: (Monoid w, Monad m) => WT w m a -> (m a, w)
unWT (WT cmaw) = cmaw
现在我正在尝试定义monad (WT w m)
,但没有成功:
instance (Monoid w, Monad m) => Monad (WT w m) where
return x = WT (return x, mempty)
wtwma >>= fawtwmb = WT $ let (ma, w1) = unWT wtwma
(mb, w2) = unWT $ do a <- ma
fawtwmb a
in (mb, mappend w1 w2)
错误位于do-expression中,我尝试从a
中提取ma
:
Expected type: WT w m a, Actual type: m a
我尝试了一些变化,总是有类似的结果。我无法为此monad定义bind
。
我的主要问题是:如果monad在一对夫妇中,我如何提取其价值?
答案 0 :(得分:6)
想象一下以下计算:
tellLine :: WT String IO ()
tellLine = do
input <- WT (getLine, "")
WT (return (), input)
impossible :: String
impossible = snd (unWT tellLine)
如果这是&#34;期望&#34;,我们应该得到impossible
是用户输入的字符串。但是,我们不能在IO
之外执行此操作;这样的impossible
不能像这里一样纯String
。因此,不可能产生一个w
作为monad计算结果而被收到的。
另一种可能性就是返回第一次绑定之前发生的w
,因此我们不必依赖任何monadic动作。唉,其中一个身份法律阻止了我们。
return x >>= f = f x
在这里我们可以看到&#34;在第一次绑定之前#34;不能是一个有意义的概念,因为左边有一个绑定而右边没有绑定。因此,返回在第一次绑定之前发生的w
肯定会违反此monad法则。
唯一剩下的可能性是w
始终为mempty
。但由于其他身份法,这也不起作用。
m >>= return = m
因此,如果m
的非mempty
值为w
,则绑定会消灭它并违反此法律。
这个WT
cannote是monad变换器。有一个WriterT
变换器,但定义为m (a,w)
可以避免这些问题。