Reputation: 321
I was playing with the Reader monad in Purescript and I encountered a weird behaviour. I don't know if it's because my lack of comprehension of this monad or if I'm missing something else.
This is my code :
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)
This is okay and will compile. Nevertheless, before this I tried something simpler in my function line like this :
line :: String -> Doc
line s = do
level <- ask
return "Hello Reader monad"
And it won't compile, despite the fact that (renderLine s level) and "Hello Reader monad" has the same type. It will throw me this error : "No instance found for Control.Monad.Reader.Class.MonadReader u14555 (Control.Monad.Reader.Trans.ReaderT Prim.Number Control.Monad.Identity.Identity)"
I'm sure I'm missing something, but I don't know what.
Upvotes: 2
Views: 363
Reputation: 4649
A more readable version of that error would be:
No instance found for MonadReader ? (Reader Number)
I think the problem here is due to the lack of functional dependencies in PureScript - in Haskell the MonadReader
class is defined as MonadReader r m | m -> r
so r
is decided by m
, but we can't do that in PureScript.
I suspect the reason it works in the former case rather than the latter is type of level
is being unified with Level
in the call to renderLine
, which means r
must therefore also be Level
.
As you're not doing anything with level
in the latter case, the type variable is left un-unified, and that's where the error comes from as there is indeed no instance for MonadReader when r
is unknown.
Upvotes: 7