我正在通过 Learn You A Haskell 一书了解 Writer Monad。
这是一段代码:
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber num = writer (num, ["Got number: " ++ show num])
multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (a * b)
运行
multWithLog
时,结果如下:*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5"])
在这一行:
a <- logNumber 3
b <- logNumber 5
很容易看到
a = 3
和 b = 5
,因为它们都在 return
函数上相乘。我不明白的是为什么这些值是
3
和 5
。 a
和 b
不应该是包含在 Writer
Monad 中的值吗?在这种情况下元组?例如,使用
Maybe
Monad,a
和 b
将是 3
和 5
:do
a <- Just 3
b <- Just 5
return (a * b)
在这种情况下,这对我来说很有意义,因为
a
和 b
接收 Just
中的内容。但是对于初始示例,a
和 b
仅接收部分值。 最佳答案
不。我认为回答这个问题的最简单方法是实现 Writer
类型并研究它的 Monad
类实例:
newtype Writer w a = Writer { runWriter :: (a, w) }
instance Functor (Writer w) where
fmap f (Writer (a, w)) = Writer (f a, w)
instance Monoid w => Applicative (Writer w) where
pure a = Writer (a, mempty)
Writer (f, w) <*> Writer (a, w') = Writer (f a, w <> w')
instance Monoid w => Monad (Writer w) where
return = pure
Writer (a, w) >>= f = let (b, w') = runWriter (f a)
in Writer (b, w <> w')
tell :: w -> Writer w ()
tell w = Writer ((), w)
正如您在
>>=
的实例方法中所见,函数 f
应用于 a
值,而不是整个元组。语法 a <- logNumber 3
使用 >>=
去糖化,因此绑定(bind)到 a
的值将是 Writer
环绕的元组的第一个元素。关于haskell - 理解 Writer Monad 的例子,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33881822/