尝试将以下代码加载到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
函数是否该代码示例应该如何工作。
答案 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有关于如何以不同方式导入模块的大量文档(仅导入特定符号,导入模块而不导入特定符号等)。