Wri-6ren">
gpt4 book ai didi

haskell - LYAH - 在链接 Writer monad 时理解关于 "tell"的评论

转载 作者:行者123 更新时间:2023-12-02 02:14:09 24 4
gpt4 key购买 nike

问题在底部以粗体显示。
LYAH 给出了使用 do 的示例Writer 的符号单子(monad)

import Control.Monad.Writer

logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["number " ++ show x])

multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (x*y)
可以在没有 do 的情况下重写定义符号:
multWithLog = logNumber 3 >>= (\x ->
logNumber 5 >>= (\y ->
return (x*y)))
到目前为止,一切都很好。
之后本书介绍 tell , 并编辑 multWithLog 的定义像这样:
multWithLog = do
a <- logNumber 3
b <- logNumber 5
tell ["something"]
return (x*y)
这又可以重写为:
multWithLog = logNumber 3 >>= (\x ->
logNumber 5 >>= (\y ->
tell ["something"] >>
return (x*y)))
然后这本书提出了一个对我来说似乎不清楚的观点,如果不是不准确的话:

It's important that return (a*b) is the last line, because the result of the last line in a do expression is the result of the whole do expression. Had we put tell as the last line, () would have been the result of this do expression. We'd lose the result of the multiplication. However, the log would be the same.


因此,我的第一个疑问来了:如果 tell结果 () ,那么代码不应该也不应该编译,因为 ()无法匹配预期类型 Int , 也不是 () 以外的任何其他类型本身;那么作者想告诉我们什么?为了使这个非基于意见, 自从本书编写以来,Haskell 中是否发生了一些变化,导致上述引用的陈述不清楚/不准确?

最佳答案

等效的重写是进一步

multWithLog = logNumber 3        >>= (\ x ->
logNumber 5 >>= (\ y ->
tell ["something"] >>= (\ () -> -- () NB
return (x*y) >>= (\ result ->
return result ))))
那就是 ()tell ["something"] “回归”。显然,洗牌
multWithLog2 = logNumber 3        >>= (\ x ->
logNumber 5 >>= (\ y ->
return (x*y) >>= (\ result ->
tell ["something"] >>= (\ () ->
return () ))))
确实会有类型 Writer [String] () , 所以如果签名指定 Writer [String] Int ,它确实不会编译。
没有类型签名问题,即“日志”,即收集的 [String]两个变体的列表将相同,如 return不会更改收集的输出“日志”。

关于haskell - LYAH - 在链接 Writer monad 时理解关于 "tell"的评论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62182040/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com