无法编译《学Haskell》中的Writer Monad示例

13
以下代码来自LYAH,无法编译。下面附上代码和编译时的错误信息。在LYAH页面中,该代码位于页面下方约15%的位置,感谢emacs浏览器:)
你有什么想法吗?我是否忽略了一些非常明显的东西?
(尽管标题相似,但我认为我的问题与此问题不同。)
这是代码(保存在我命名为testcopy.hs的文件中)
import Control.Monad.Writer

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

multWithLog :: Writer [String] Int
multWithLog = do
    a <- logNumber 3
    b <- logNumber 5
    return (a*b)

这里是编译时错误:

Prelude> :l testcopy.hs
[1 of 1] Compiling Main             ( testcopy.hs, interpreted )
testcopy.hs:4:15:
    Not in scope: data constructor `Writer'
    Perhaps you meant `WriterT' (imported from Control.Monad.Writer)
Failed, modules loaded: none.
2个回答

20

LYAH在这个例子中已经过时了。你应该使用writer智能构造方法代替(现在不存在的)Writer数据构造函数。

稍微解释一下,这些数据类型已更新为与单子变换器更兼容。因此,有一个通用的WriterT,用于在单子变换器堆栈中使用,以及一个将WriterTIdentity组合的Writer类型同义词。由于这个原因,不再有特定与Writer类型关联的数据构造函数(因为Writer是一个类型同义词)。

幸运的是,尽管存在这种复杂性,解决方案非常简单:用writer替换Writer


13
保持类型签名不变。将函数调用中的 Writer 替换为 writer。类型签名中以小写字母开头的部分始终指代类型变量,这并不是我们在这里想要的。我们需要具体类型的 Writer - David Young
1
我的意思是,谁不想要一台实体打字机呢? - N3dst4
@justinhj 关于您的编辑,Control.Monad.WriterControl.Monad.Trans.Writer 都导出了 Writer(以及主要相关内容),因此不需要更改导入。 - David Young
1
抱歉,那种情况下需要特定的软件包吗?当我导入Control.Monad.Writer时,会出现“找不到模块”的错误,而我已经安装了标准的Haskell平台。 - justinhj
1
@justinhj 嗯,那很奇怪,Haskell平台应该自带必要的包。如果您想尝试安装它,它是mtl这个似乎表明Haskell平台应该包括它,但安装它值得一试。 - David Young
显示剩余2条评论

2
在 GHC 7.10.3 中,正确的版本应该是这样的。
import Control.Monad.Writer

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

multWithLog :: Writer [String] Int
multWithLog = do
    a <- logNumber 3
    b <- logNumber 5
    return (a*b)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接