我正在玩Purescript中的Reader monad,我遇到了一个奇怪的行为。我不知道是不是因为我对这个monad缺乏理解,或者我错过了其他的东西。
这是我的代码:
type Level = Number
type Doc = Reader Level String
renderLine :: String -> Level -> String
renderLine s 0 = s
renderLine s l = "\t" ++ (renderLine s (l - 1))
line :: String -> Doc
line s = do
level <- ask
return (renderLine s level)
这没关系并且会编译。然而,在此之前,我在我的功能行中尝试了一些更简单的东西:
line :: String -> Doc
line s = do
level <- ask
return "Hello Reader monad"
它不会编译,尽管事实上(renderLine s level)和&#34; Hello Reader monad&#34;具有相同的类型。它会给我这个错误: &#34;没有为Control.Monad.Reader.Class.MonadReader发现实例u14555(Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)&#34;
我确定我错过了什么,但我不知道是什么。
答案 0 :(得分:7)
该错误的更易读的版本是:
No instance found for MonadReader ? (Reader Number)
我认为这里的问题是由于PureScript中缺少功能依赖性 - 在Haskell中MonadReader
类被定义为MonadReader r m | m -> r
所以r
由m
决定,但我们不能在PureScript中这样做。
我怀疑它在前一种情况下起作用的原因而不是后一种情况level
的类型在调用Level
时与renderLine
统一,这意味着{{1}因此,必须r
。
由于你在后一种情况下没有对Level
做任何事情,因此类型变量不统一,而且错误的来源是因为确实没有实例level
未知时的MonadReader。