I am currently trying to understand the do notation as taught in: http://learnyouahaskell.com/for-a-few-monads-more ...Here it is applied to simple functions and not a monad.
type Stack = [Int]
push :: Int -> Stack -> ((), Stack)
push a stack = ((),a:stack)
pop :: Stack -> (Int, Stack)
pop (x:xs) = (x, xs)
I dont understand the do-syntax fully, I am curious: Is this
turnipStack2 :: Stack -> (Int, Stack)
turnipStack = do
push 3
c <- pop
pop
.. the same as
turnipStack :: Stack -> (Int, Stack)
turnipStack = do
push 3
c <- pop
return c
If so, why is that. And could I have done the first mentioned without writing pop in the end. In that case I get an error although I don't understand it.
First, to actually get this working you need to change the signatures to use the state monad. Currently your
doblock refers to the(Stack->)monad, akaReader Stack, but you wantState Stackinstead.This is not equivalent to
The latter just pops off the one element you stored again, and then gives it back. This could actually be simplified to
thanks to the monad law
do{ x<-a; return x } ≡ a(right identity).By contrast,
turnipStack2first pops off the3you pushed, but doesn't use it (it's just discarded) then pops off another element which is the result value.Applying the right identity law in reverse, you could however write it thus:
Binding an unused variable can be omitted, so