难以理解歧义发生的“作家”#39;错误

时间:2016-12-06 13:59:05

标签: haskell

尝试将以下代码加载到ghci中时:

import Control.Monad.Writer

newtype Writer w a = Writer { runWriter :: (a, w) } 

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)  

(来自http://learnyouahaskell.com/for-a-few-monads-more

我收到此错误:

writer1.hs:8:16: error:
    Ambiguous occurrence `Writer'
    It could refer to either `Control.Monad.Writer.Writer',
                             imported from `Control.Monad.Writer' at writer1.hs:1:1-27
                             (and originally defined in `Control.Monad.Trans.Writer.Lazy')
                          or `Main.Writer', defined at writer1.hs:3:1
Failed, modules loaded: none.

我已阅读有关SO的相关问题,例如: Ambiguous occurrence `Just' 但我仍然在努力寻找如何在我的案例中最好地应用这一点。 除了这个特定的问题,如果你能指出如何避免类似的命名歧义的任何约定,那将是很好的。

编辑: 正如@chi在评论中指出的那样,我可以跳过newtype Writer w a = Writer { runWriter :: (a, w) },然后使用提供的函数writer而不是Writer构造函数。但是,这与本书中的代码(使用Writer)不同,当我在REPL中调用它时,它会向我显示另一种类型WriterT

*Main> logNumber 3
WriterT (Identity (3,["Got number: 3"]))

所以我仍然不确定使用writer函数是否该代码示例应该如何工作。

1 个答案:

答案 0 :(得分:1)

如果您想按照本书中的练习进行操作,并亲自实施Writer,那么只需从代码中删除import Control.Monad.Writer即可。

看起来好像这本书改为使用Control.Monad.Writer “在编写器上使用do notation”,因此您只需删除自己对Writer的定义并使用import Control.Monad.Writer

Control.Monad.Writer会导出类型Writer,因此会与您自己的类型发生冲突。

如果您想要无论如何使用Control.Monad.Writer中的方法或类型,您可以使用其他名称导入它。例如。 import qualified Control.Monad.Writer as MW,然后您可以将Writer定义为MW.Writer,将您自己定义为Writer

Haskell wiki有关于如何以不同方式导入模块的大量文档(仅导入特定符号,导入模块而不导入特定符号等)。