为自制的monad变换器定义绑定

时间:2015-07-13 20:02:24

标签: haskell monads monad-transformers

我已经定义了我自己的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在一对夫妇中,我如何提取其价值?

1 个答案:

答案 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)可以避免这些问题。