2

我在 Purescript 中玩 Reader 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) 和 "Hello Reader monad" 具有相同的类型。它会给我这个错误:“没有找到 Control.Monad.Reader.Class.MonadReader u14555 的实例(Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)”

我确定我错过了一些东西,但我不知道是什么。

4

1 回答 1

7

该错误的更具可读性的版本是:

No instance found for MonadReader ? (Reader Number)

我认为这里的问题是由于 PureScript 中缺乏函数依赖关系——在 Haskell 中,MonadReader类的定义MonadReader r m | m -> rr由 决定的m,但在 PureScript 中我们不能这样做。

我怀疑它在前一种情况下而不是在后一种情况下起作用的原因是 type of在调用中level被统一,因此也必须是。LevelrenderLinerLevel

由于在后一种情况下您没有做任何事情level,因此类型变量未统一,这就是错误的来源,因为在r未知时确实没有 MonadReader 的实例。

于 2015-03-17T14:54:45.883 回答