Can Recursive-Do Be Desugared - haskell

Can a recursive-do statement be desugared to a series of >>= statements? If so, what does the reverse state monad's definition for >>= look like when it's desugared?
instance MonadFix m => Monad (StateT s m) where
return x = ...
m >>= f = StateT $ \s -> do
rec
(x, s'') <- runStateT m s'
(x', s') <- runStateT (f x) s
return (x', s'')

Recursive-do desugars not only to a series of >>= calls, but also, as long as there is actually recursion, into an mfix call. It is in the mfix call that the whole recursiveness happens, via what is technically termed "magic fairy dust".
Seriously though, how it happens is different for every monad, and that's why it's a class MonadFix rather than just a function. But the important point is that it can "magically" pass you your own result as a parameter, which is only possible due to Haskell's laziness, and therefore must be handled with care.
In general, something like this:
do
rec
x <- f y
y <- g x
return $ h x y
Desugars into this:
mfix (\ ~(x, y) -> do
x' <- f y
y' <- g x'
return (x', y')
)
>>= (\(x, y) -> h x y)
So applying to the reverse state definition, it would look like this:
m >>= f = StateT $ \s ->
mfix (\ ~((x, s''), (x',s')) -> do
(x0, s0'') <- runStateT m s'
(x0', s0') <- runStateT (f x0) s
return ((x0, s0''), (x0', x0'))
)
>>= (\(x, s''), (x',s') -> return (x', s''))
And from here, we can just desugar the regular do as usual:
m >>= f = StateT $ \s ->
mfix (\ ~((x, s''), (x',s')) ->
runStateT m s' >>= \(x0, s0'') ->
runStateT (f x0) s >>= \(x0', s0') ->
return ((x0, s0''), (x0', x0'))
)
>>= (\(x, s''), (x',s') -> return (x', s''))
(that is, unless I messed up something - a lot of ticks flying around :-)

Related

proving monad laws of a new monad instance (list of maybe)

I made a new List of Maybe Monad instance and tried to prove the implementation does satisfy the Monad laws, am I doing it right or is the implementation incorrect? Any pointer is appreciated. Thanks!
newtype Test a = Test { getTest :: [Maybe a] }
deriving Functor
instance Applicative Test where
pure = return
(<*>) = liftM2 ($)
instance Monad Test where
return :: a -> Test a
return a = Test $ [Just a]
(>>=) :: Test a -> (a -> Test b) -> Test b
Test [Nothing] >>= f = Test [Nothing]
Test [Just x] >>= f = f x
{-
1. return x >>= f = f x
return x >>= f = [Just x] >>= f = f x
2. m >>= return = m
[Nothing] >>= return = [Nothing]
[Just x] >>= return = return x = [Just x]
3. (m >>= f) >>= g == m >>= (\x -> (f x >>= g))
m = [Nothing]
L.H.S. = ([Nothing] >>= f ) >>= g = Nothing >>= g = Nothing
R.H.S. = [Nothing] >>= (\x -> (f x >>= g)) = Nothing
m = [Just x]
L.H.S. = ([Just x] >>= f) >>= g = f x >>= g
R.H.S. = [Just x] >>= (\v -> (f v >>= g)) = (\v -> (f v >>= g)) x
= f x >>= g
-}
The bits of the proof you have written are only incorrect in unimportant ways. Specifically, in these two lines:
([Nothing] >>= f ) >>= g = Nothing >>= g = Nothing
[Nothing] >>= (\x -> (f x >>= g)) = Nothing
The three bare Nothings should be [Nothing]s.
However, the proof is incomplete, because there are values of type Test a that are neither of the form [Just (x :: a)] nor [Nothing]. This makes the proof as a whole incorrect in an important way.

Understanding do notation for simple Reader monad: a <- (*2), b <- (+10), return (a+b)

instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
I'm trying to understand this monad by unwiding the do notation, because I think the do notation hides what happens.
If I understood correctly, this is what happens:
(*2) >>= (\a -> (+10) >>= (\b -> return (a+b)))
Now, if we take the rule for >>=, we must understand (*2) as h and (\a -> (+10) >>= (\b -> return (a+b))) as f. Applying h to w is easy, let's just say it is 2w (I don't know if 2w is valid in haskell but just for reasoning lets keep it this way. Now we have to apply f to h w or 2w. Well, f simply returns (+10) >>= (\b -> return (a+b)) for an specific a, which is 2w in our case, so f (hw) is (+10) >>= (\b -> return (2w+b)). We must first get what happens to (+10) >>= (\b -> return (2w + b)) before finally applying it to w.
Now we reidentify (+10) >>= (\b -> return (2w + b)) with our rule, so h is +10 and f is (\b -> return (2w + b)). Let's first do h w. We get w + 10. Now we need to apply f to h w. We get (return (2w + w + 10)).
So (return (2w + w + 10)) is what we need to apply to w in the first >>= that we were tyring to uwind. But I'm totally lost and I don't know what happened.
Am I thinking in the rigth way? This is so confusing. Is there a better way to think of it?
You're forgetting that operator >>= doesn't return just f (h w) w, but rather \w -> f (h w) w. That is, it returns a function, not a number.
By substituting it incorrectly you lost the outermost parameter w, so it's no wonder it remains free in your final expression.
To do this correctly, you have to substitute function bodies for their calls completely, without dropping stuff.
If you substitute the outermost >>=, you will get:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
Then, if you substitute the innermost >>=, you get:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
Note that I use w1 instead of w. This is to avoid name collisions later on when I combine the substitutions, because these two ws come from two different lambda abstractions, so they're different variables.
Finally, substitute the return:
return (a+b)
==
\_ -> a+b
Now insert this last substitution into the previous one:
\a -> (+10) >>= (\b -> return (a+b))
==
\a -> \w1 -> (\b -> return (a+b)) (w1 + 10) w1
==
\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1
And finally insert this into the very first substitution:
(*2) >>= (\a -> ...)
==
\w -> (\a -> ...) (w*2) w
==
\w -> (\a -> \w1 -> (\b -> \_ -> a+b) (w1 + 10) w1) (w*2) w
And now that all substitutions are compete, we can reduce. Start with applying the innermost lambda \b -> ...:
\w -> (\a -> \w1 -> (\_ -> a+w1+10) w1) (w*2) w
Now apply the new innermost lambda \_ -> ...:
\w -> (\a -> \w1 -> a+w1+10) (w*2) w
Now apply \a -> ...:
\w -> (\w1 -> w*2+w1+10) w
And finally apply the only remaining lambda \w1 -> ...:
\w -> w*2+w+10
And voila! The whole function reduces to \w -> (w*2) + (w+10), completely as expected.
First, we write out the implicit argument in your definition explicitly,
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
=
addStuff :: Int -> Int
addStuff x = ( do
a <- (*2)
b <- (+10)
return (a+b) ) x
=
....
Then, with
return x = const x
(f =<< h) w = f (h w) w -- (f =<< h) = (h >>= f)
it should be easier to follow and substitute the definitions, line for line:
....
=
( (*2) >>= (\a -> -- (h >>= f) =
(+10) >>= (\b ->
const (a+b) ) ) ) x
=
( (\a -> -- = (f =<< h)
(+10) >>= (\b ->
const (a+b) ) ) =<< (*2) ) x -- (f =<< h) w =
=
(\a ->
(+10) >>= (\b ->
const (a+b) ) ) ( (*2) x) x -- = f (h w) w
=
( let a = (*2) x in -- parameter binding
(+10) >>= (\b ->
const (a+b) ) ) x
=
let a = (*2) x in -- float the let
((\b ->
const (a+b) ) =<< (+10) ) x -- swap the >>=
=
let a = (*2) x in
(\b -> -- (f =<< h) w =
const (a+b) ) ( (+10) x) x -- = f (h w) w
=
let a = (*2) x in
(let b = (+10) x in -- application
const (a+b) ) x
=
let a = (*2) x in -- do a <- (*2)
let b = (+10) x in -- b <- (+10)
const (a+b) x -- return (a+b)
The essence of reader monad is application to same argument shared between all calls.
Intuitively, each function call on the right-hand side of the <- is given an additional argument, which you can think of as the argument to addStuff itself.
Take
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
and turn it into
addStuff :: Int -> Int
addStuff x = let a = (*2) x
b = (+10) x
in (a+b)
It looks a little less "strange" if you use the MonadReader instance for (->) r, which provides ask as a way to get direct access to the implicit value.
import Control.Monad.Reader
addStuff :: Int -> Int
addStuff = do
x <- ask -- ask is literally just id in this case
let a = x * 2
let b = x + 10
return (a + b)

How binding works in function monads in Haskell?

From learn you a haskell: http://learnyouahaskell.com/for-a-few-monads-more
Monad instance for function is this:
instance Monad ((->) r) where
return x = \_ -> x
h >>= f = \w -> f (h w) w
I am having trouble understanding the output of the following:
import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
addStuff 3 returns 19. Book says 3 gets passed as parameters to both (*2) and (+10). How?
From h >>= f = \w -> f (h w) w , it seems like (h w) is getting bound to a or b.
So, why 6 is not being passed in (+10)?
My understanding of f here is that when (*2) is h, f is the last 2 lines of addStuff. When (+10) is h, f is the last line (in this case the return statement) of addStuff.
Let us first desugar the do block [Haskell'10 report]:
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)
is equivalent to:
addStuff = (*2) >>= \a -> ((+10) >>= \b -> return (a + b))
The inner bind expression ((+10) >>= \b -> return (a + b)), can thus be converted, with the bind definition to:
\w -> (\b -> return (a + b)) ((+10) w) w
and if we substitute return with const, we thus obtain:
\w -> (const . (a+)) ((+10) w) w
We thus have a function that takes as input w, and then calls const . (a+) on (w+10) and w, so it will ignore the last w. Semantically it is equivalent to:
(a+) . (+10)
So now our addStuf is equivalent to:
addStuff = (*2) >>= \a -> ((a+) . (+10))
and if we now use the definition for the bind operator again, we see:
\w -> (\a -> ((a+) . (+10))) ((*2) w) w
or shorter:
\w -> (\a -> ((a+) . (+10))) (w*2) w
We can now substitue a with (w*2) and obtain:
\w -> ((w*2)+) . (+10)) w
So our addStuf is equivalent to:
addStuff w = (w*2) + (w+10)
or more simple:
addStuff w = 3*w + 10
Haskell do notation is syntactic sugar for a series of >>= bindings; in this case, for something like this:
addStuff = (*2) >>= (\a -> (+10) >>= (\b -> return (a + b)))
Passing the updated argument between the computation steps (which would thus be serving a role of a state) is the job of another monad, namely the State monad.
The function aka Reader monad is simpler than that, does less work:
-- (return x) w = x
-- (h >>= f) w = f (h w) w
(h >>= (\a -> g >>= (\b -> return (f a b)))) w
=
(\a -> g >>= (\b -> return (f a b))) (h w) w
=
(g >>= (\b -> return (f (h w) b))) w
=
(\b -> return (f (h w) b))) (g w) w
=
return (f (h w) (g w)) w
=
f (h w) (g w)
Thus the input argument w is passed unchanged into both (by extension, all) the computation steps. Or in the specific case you ask about,
liftM2 (+) ( *2) ( +10) w
=
(+) (w*2) (w+10)
liftM2 function is equivalent to the do block that you show,
liftM2 f h g =
do {
a <- h ;
b <- g ;
return (f a b) }
=
h >>= (\ a ->
g >>= (\ b -> return (f a b) ))
in any monad.

Concise way to conditionally update map in State monad

Below is the code from an answer regarding memoization, showing a memoization function used in the State monad, where the state is updated with the result of the passed function if the key is not already in the map.
type MyMemo a b = State (Map.Map a b) b
myMemo :: Ord a => (a -> MyMemo a b) -> a -> MyMemo a b
myMemo f x = do
map <- get
case Map.lookup x map of
Just y -> return y
Nothing -> do
y <- f x
modify $ \map' -> Map.insert x y map'
return y
It doesn't seem like idiomatic Haskell: it feels very imperative, with not really that much going on per line.
Is there a way to do the above, but in a more concise/functional style? I've had a look around the functions available at http://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-Monad-Trans-State-Lazy.html#v:state, but nothing really seems helpful.
I think your code is in functional style, but you can bit simplify it.
myMemo f x = maybe work return =<< gets (Map.lookup x)
where
work = do
y <- f x
modify $ Map.insert x y
return y
This is alternative that uses mapState, as well as >>= and maybe from https://stackoverflow.com/a/44515364/1319998, that avoids all the do notation
myMemo f x = gets (Map.lookup x) >>= maybe y' return
where
y' = mapState (\(y, map) -> (y, Map.insert x y map)) $ f x
This is an alternative that expands on https://stackoverflow.com/a/44515364/1319998, using more >>= that avoids all the do notation
myMemo :: Ord a => (a -> MyMemo a b) -> a -> MyMemo a b
myMemo f x = gets (Map.lookup x) >>= maybe y' return
where
y' = f x >>= \y -> state $ \map -> (y, Map.insert x y map)
This is an alternative that expands on https://stackoverflow.com/a/44515364/1319998, essentially de-sugaring the do-notation
myMemo f x = gets (Map.lookup x) >>= maybe y' return
where
y' = f x >>= \y -> modify (Map.insert x y) >> return y

unbound variables in monad associativity law

Using ghci I have computed:
Prelude> let m = [1,2]
Prelude> let ys = [4, 5, 6]
Prelude> m >>= (\x -> ys >>= (\y -> return (x, y)))
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6)]
The monadic expression above doesn't seem to correspond to either side of the monad associativity law:
(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
I would like to know how monad associativity can be applied to the expression:
m >>= (\x -> ys >>= (\y -> return (x, y)))
Because return (x,y) closes on both the surrounding function and the one containing it, it seems that an intermediate monad, as exists on the left side of the associativity law (m >>= f), cannot exist in this example.
I think that you're confusing the monadic laws for the structure of a monadic expression. The monadic associativity law states that the expression (m >>= f) >>= g must be equivalent to the expression m >>= (\x -> f x >>= g) for the data type of m to be considered a monad.
This does not imply that every monadic expression must be of the form (m >>= f) >>= g.
For example m >>= f is a perfectly valid monadic expression even though it's not of the form (m >>= f) >>= g. However it still obeys the monadic associativity law because m can be expanded to m >>= return (from the monadic right identity law m >>= return ≡ m). Hence:
m >>= f
-- is equivalent to
(m >>= return) >>= f
-- is of the form
(m >>= f) >>= g
In your example m >>= (\x -> ys >>= (\y -> return (x, y))) is of the form m >>= f where f is \x -> ys >>= (\y -> return (x, y)).
Although \x -> ys >>= (\y -> return (x, y)) is not of the form \x -> f x >>= g (from the right hand side of the monadic associativity law) it doesn't mean that it breaks the monadic laws.
The expression m >>= (\x -> ys >>= (\y -> return (x, y))) can be expanded into the monadic associative form by substituting m >>= return for m:
(m >>= return) >>= (\x -> ys >>= (\y -> return (x, y)))
-- is of the form
(m >>= f) >>= g
-- and can be written as
m >>= (\x -> return x >> (\x -> ys >>= (\y -> return (x, y))))
Hope that clarifies things.
Indeed, it's not possible to directly apply the associative law, because of the scope of x in the original expression:
import Control.Monad (liftM)
test = let m = [1,2]
ys = [4, 5, 6]
in m >>= (\x -> ys >>= (\y -> return (x, y)))
However, we can reduce the scope of x if we include it into the result of the first monadic computation. Instead of returning [Int] in x -> ys, we'll use \x -> liftM ((,) x) ys and return [(Int,Int)], where the first number in each pair is always x and the second is one of ys. (Note that for lists liftM is the same as map.) And the second function will read the value of x from its input:
test1 = let m = [1,2]
ys = [4, 5, 6]
in m >>= (\x -> liftM ((,) x) ys >>= (\(x', y) -> return (x', y)))
(The monadic function \(x', y) -> return (x', y) could be now simplified just to return, and subsequently >>= return removed completely, but let's keep it there for the sake of the argument.)
Now each monadic function is self-contained and we can apply the associativity law:
test2 = let m = [1,2]
ys = [4, 5, 6]
in (m >>= \x -> liftM ((,) x) ys) >>= (\(x, y) -> return (x, y))
The monadic law applies to functions of one arguments only. The expression
xs >>= (\x -> ys >>= (\y -> (x, y)))
is really equivalent to:
xs >>= \x -> fmap ($ x) $ ys >>= \y -> return (\x -> (x,y))
(if we were to avoid capturing x)
So you can't apply the same laws - we have fmap as f and no g from the associativity law.
The above is of course the same as:
xs >>= \x -> fmap ($ x) $ fmap (\y x -> (x,y)) ys
or
xs >>= \x -> fmap (\y -> (x,y)) ys

Resources