Reputation: 1497
I am relatively new to Haskell. Now I am trying to understand the Reader Monad more fully. It seems to be clearer the purpose and usage of it. But in Haskell while viewing the type of :t reader
function I see reader :: MonadReader r m => (r -> a) -> m a
. What does this type constraint mean?
When I am trying to construct Reader, e.g
let myR = reader (\x -> x + 10)
I see error
<interactive>:21:11:
No instance for (MonadReader a0 m0) arising from a use of `reader'
The type variables `m0', `a0' are ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance MonadReader r' m =>
MonadReader r' (Control.Monad.Trans.Cont.ContT r m)
-- Defined in `Control.Monad.Reader.Class'
instance MonadReader r ((->) r)
-- Defined in `Control.Monad.Reader.Class'
instance (Control.Monad.Trans.Error.Error e, MonadReader r m) =>
MonadReader r (Control.Monad.Trans.Error.ErrorT e m)
-- Defined in `Control.Monad.Reader.Class'
...plus 10 others
In the expression: reader (\ x -> x + 10)
In an equation for `myR': myR = reader (\ x -> x + 10)
<interactive>:21:27:
No instance for (Num a0) arising from a use of `+'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Num Double -- Defined in `GHC.Float'
instance Num Float -- Defined in `GHC.Float'
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus three others
In the expression: x + 10
In the first argument of `reader', namely `(\ x -> x + 10)'
In the expression: reader (\ x -> x + 10)
It is clear that I should add type signature:
let myR = reader (\x -> x + 10) :: Reader Int Int
This works but how I could imply from this definition of reader reader :: MonadReader r m => (r -> a) -> m a
that I should define it as Reader Int Int
?
(In case of Maybe, e.g. let m5 = return 5 :: Maybe Int
it seems to be clear for me, probably because of Maybe has one type parameter, I am not sure)
Upvotes: 1
Views: 159
Reputation: 19221
While it would be able to default the Int
Haskell doesn't default the Monad
to Reader
.
let myR = reader (\x -> x + 10) :: Num a, MonadReader a m => m a
Is roughly what the type checker finds, then it applies a defaulting rule for Num
to Int
and gets.
let myR = reader (\x -> x + 10) :: MonadReader Int m => m Int
However it has no default defined for MonadReader
so has to return an ambiguous error at this point.
All isn't lost though, you can annotate some other part of the program if you don't want to annotate myR
, the type checker just eventually needs to be told which MonadReader
you want.
Upvotes: 1