Interpreting Haskell monad example

2019-09-21 15:17发布

问题:

I have this Haskell code that triples input value.

triple :: Int -> Int
triple = do
  n <- id
  d <- (n+)
  (d+)

How does this code work? With an example triple 10, how the argument 10 is mapped/assigned to id, n and d to get the return value of 30?

My understandig is as follows:

We can decompose triple function with two subfunctions tripleA and tripleB as follows:

triple :: Int -> Int
triple = tripleA >>= (\d -> tripleB d)

tripleA :: Int -> Int
tripleA = id >>= (\n -> (n+))

tripleB :: Int -> Int -> Int
tripleB d = (d+)

Now we can see that the function tripleA gets an input, assign it to id function to return the value itself, and map it to the function (\n -> (n+)) to return (10+) 10.

Likewise, tripleB also makes (20+) 20, so I expect the results as 40, but the correct answer is 30.

What is wrong with my interpretation?

回答1:

We can rewrite equivalent triple2 function as follows:

triple2 = (id >>= (\n -> (n+))) >>= (\d -> (d+))

With f = \n -> (n+), we have triple2 = (id >> f) >> f.

From the definition of >>= in (https://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.Base.html#line-645), we have

1. id >>= f

\r -> f (id r) r = \r -> f r r = \r -> (r+) r

2. (id >>= f) >>= f

x = id >>= f = \r -> (r+) r
x r = (r+) r
x >> f = \r -> f (x r) r = f ((r+) r) r = ((r+) r)+ r

so ((10+) 10)+ 10 makes 30