我正在通过 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 = 3b = 5 ,因为它们都在 return 函数上相乘。

我不明白的是为什么这些值是 35ab 不应该是包含在 Writer Monad 中的值吗?在这种情况下元组?

例如,使用 Maybe Monad,ab 将是 35 :
do
  a <- Just 3
  b <- Just 5
  return (a * b)

在这种情况下,这对我来说很有意义,因为 ab 接收 Just 中的内容。但是对于初始示例,ab 仅接收部分值。

最佳答案



不。我认为回答这个问题的最简单方法是实现 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/

10-16 08:31