Reader Purescript 中的 Monad

Reader Monad in Purescript

我在 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) 和 "Hello Reader monad" 具有相同的类型。它会抛出这个错误: "No instance found for Control.Monad.Reader.Class.MonadReader u14555 (Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)"

我确定我遗漏了什么,但我不知道是什么。

该错误的更易读版本是:

No instance found for MonadReader ? (Reader Number)

我认为这里的问题是由于 PureScript 中缺少函数依赖 - 在 Haskell 中 MonadReader class 被定义为 MonadReader r m | m -> r 所以 rm 决定,但我们不能在 PureScript 中这样做。

我怀疑它在前一种情况下而不是在后者中起作用的原因是 level 的类型在对 renderLine 的调用中与 Level 统一,这意味着 [=因此 13=] 也必须是 Level.

因为在后一种情况下你没有对 level 做任何事情,所以类型变量是不统一的,这就是错误的来源,因为当 [= 时确实没有 MonadReader 的实例13=] 未知。