为自制的 monad 转换器定义绑定
Defining bind for home-made monad transformer
我已经定义了我自己的 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 表达式中,在我尝试从 ma
中提取 a
的位置:
Expected type: WT w m a, Actual type: m a
我尝试了一些变体,结果总是相似的。我无法为这个 monad 定义 bind
。
我的主要问题是:如果 monad 在一对内部,我如何提取它的值?
设想以下计算:
tellLine :: WT String IO ()
tellLine = do
input <- WT (getLine, "")
WT (return (), input)
impossible :: String
impossible = snd (unWT tellLine)
如果这相当于"expected",我们应该得到impossible
是用户输入的字符串。但是,我们不能在 IO
之外这样做;这样的 impossible
不可能像这里那样是纯粹的 String
。因此,不可能产生作为 monad 计算结果收到的 w
。
另一种可能性是简单地 return 第一次绑定之前发生的 w
,因此我们不必依赖任何单子操作。 las,身份法则之一阻碍了我们。
return x >>= f = f x
这里可以看出"before the first bind"不是一个有意义的概念,因为左边有bind,右边没有。所以 return 在第一次绑定之前发生的 w
肯定会违反这个 monad 法则。
唯一剩下的可能性是 w
永远是 mempty
。但这也行不通,因为另一个恒等式。
m >>= return = m
因此,如果 m
具有 w
的非 mempty
值,绑定将消灭它并违反此法则。
这个 WT
不能是一个 monad 转换器。有一个 WriterT
变压器,但它被定义为 m (a,w)
避免了这些问题。
我已经定义了我自己的 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 表达式中,在我尝试从 ma
中提取 a
的位置:
Expected type: WT w m a, Actual type: m a
我尝试了一些变体,结果总是相似的。我无法为这个 monad 定义 bind
。
我的主要问题是:如果 monad 在一对内部,我如何提取它的值?
设想以下计算:
tellLine :: WT String IO ()
tellLine = do
input <- WT (getLine, "")
WT (return (), input)
impossible :: String
impossible = snd (unWT tellLine)
如果这相当于"expected",我们应该得到impossible
是用户输入的字符串。但是,我们不能在 IO
之外这样做;这样的 impossible
不可能像这里那样是纯粹的 String
。因此,不可能产生作为 monad 计算结果收到的 w
。
另一种可能性是简单地 return 第一次绑定之前发生的 w
,因此我们不必依赖任何单子操作。 las,身份法则之一阻碍了我们。
return x >>= f = f x
这里可以看出"before the first bind"不是一个有意义的概念,因为左边有bind,右边没有。所以 return 在第一次绑定之前发生的 w
肯定会违反这个 monad 法则。
唯一剩下的可能性是 w
永远是 mempty
。但这也行不通,因为另一个恒等式。
m >>= return = m
因此,如果 m
具有 w
的非 mempty
值,绑定将消灭它并违反此法则。
这个 WT
不能是一个 monad 转换器。有一个 WriterT
变压器,但它被定义为 m (a,w)
避免了这些问题。