I can't understand this:
Assuming t
is hidden inside a Reader Monad.
I can get to it using ask
:
do
x <- ask
...
which unpacks the hidden value into x
Now I'm trying to understand what >>=
will do but I struggle with it.
Can you explain that to me?
Here, is my attempt:
f = \x -> x
ask >>= (\x -> return x)
= Reader $ \r -> f (ask (r)) r
{ using the fact that ask is identity }
= Reader $ \r -> f(r) r
However, I don't see how this get's to the hidden value
I think the main point is, that there is really nothing hidden inside Reader
- instead it's a function - and your hidden value enters the stage when you run the reader (this is when you show your hidden value to the reader and let it evaluate to some output).
Well let's simplify things a bit and assume that the structure for our Reader
Monad is defined as this:
data Reader h a = Reader { run :: h -> a }
that means you hidden value will have some type h
and the Reader
is just a function that produces some other value (of type a
) from when presented with such a value.
As you can see there is no value hidden at all - you have to provide it yourself when running the Reader
with run
Here is an example:
showInt :: Reader Int String
showInt = Reader show
you'll use it like
λ> run showInt 5
"5" -- has type :: String
the Monad instance is basically this (you'll have to provide instances for Applicative
and Functor
too, which I'll skip)
instance Monad (Reader h) where
return v =
Reader (const v)
r >>= f = Reader $ \ h ->
let v = run r h
r' = f v
in run r' h
notice how again you wait till someone provides you with a h
(by calling run
) and then:
v
out of the reader using run rh
v
to get another reader f'
h
: run r' h
ask
well as you said: it's just the reader using id
- it will reproduce the given value when run:
ask :: Reader h h
ask = Reader id
now we can finally deal with the question:
what happens if we run
let r = ask >>= (\x -> return x)
well let's stick a "Hello" in:
run r "Hello"
{ def r }
= run (ask >>= return) "Hello"
{ def >>= }
= run (\h ->
let v = run ask h
r' = return v
in run r' h) "Hello"
{ def run: plug "Hello" into h }
= let v = run ask "Hello"
r' = return v
in run r' "Hello"
{ ask = Reader id - so run ask "Hello" = "Hello" -> v = "Hello" }
= let r' = return "Hello"
in run r' "Hello"
{ simplify }
= run (return "Hello") "Hello"
{ r' = const "Hello" = \ _ -> "Hello" }
= (\ _ -> "Hello") "Hello"
{ apply }
= "Hello"
By the way: it's a good thing that it worked out that way, because one of the monad-laws (which should hold but are not enforced by Haskell) states:
m >>= return == m
which means here, that your reader ask >>= return == ask
which would have made all this a bit easier ;)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.