简体   繁体   中英

haskell - why ask retrieves enviroment from Reader monad

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).

revisiting the definition

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

make it a Monad

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:

  • first get the value v out of the reader using run rh
  • use this v to get another reader f'
  • finally get the value of this reader by running it with the same h : run r' h

what is 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

your question

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"

laws

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM