lha*_*ahn 3 monads haskell writer-monad
我正在通过 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)
Run Code Online (Sandbox Code Playgroud)
运行时multWithLog,结果如下:
*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5"])
Run Code Online (Sandbox Code Playgroud)
在这一行:
a <- logNumber 3
b <- logNumber 5
Run Code Online (Sandbox Code Playgroud)
很容易看出a = 3and b = 5,因为它们都在return函数上相乘。
我不明白的是为什么这些值是3和5。不宜a和b是里面包含值Writer单子?在这种情况下元组?
例如,这与MaybeMonad 一起使用,a并且b将是3和5:
do
a <- Just 3
b <- Just 5
return (a * b)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这对我来说很有意义,因为a并b接收Just. 但是,随着最初的例子,a并且b仅接收值的一部分。
很容易看出 a = 3 和 b = 5,因为它们都在返回函数上相乘。我不明白的是为什么这些值是 3 和 5。a 和 b 不应该是包含在 Writer Monad 中的值吗?在这种情况下元组?
不。我认为回答这个问题的最简单方法是实现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)
Run Code Online (Sandbox Code Playgroud)
正如您在 的实例方法中所见>>=,该函数f应用于a值,而不是整个元组。使用 对语法a <- logNumber 3进行脱糖>>=,因此绑定到的值a将是Writer环绕的元组的第一个元素。