I´am trying to desugar a do statement in Haskell. I have found some examples here on SO but wasn´t able to apply them to my case. Only thing I can think of is a heavy nested let statement, which seems quite ugly.
Statement in which do notation should be replaced by bind:
do num <- numberNode x
nt1 <- numberTree t1
nt2 <- numberTree t2
return (Node num nt1 nt2)
Any input is highly appreciated =)
Translating the bind operator (>>=) passes a value, namely the result of an action or function, downstream in the binding sequence. do notation assigns a variable name to the passed value using the <- .
The next function is >>=, or bind. It's like function application, only instead of taking a normal value and feeding it to a normal function, it takes a monadic value (that is, a value with a context) and feeds it to a function that takes a normal value but returns a monadic value.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
The left arrow gets used in do notation as something similar to variable binding, in list comprehensions for the same (I'm assuming they are the same, as list comprehensions look like condensed do blocks), and in pattern guards, which have the form (p <- e). All of those constructs bind a new variable.
numberNode x >>= \num ->
numberTree t1 >>= \nt1 ->
numberTree t2 >>= \nt2 ->
return (Node num nt1 nt2)
Note that this is simpler if you use Applicatives:
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2
This is an excellent use case for applicative style. You can replace your entire snippet (after importing Control.Applicative
) with
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2
Think of the applicative style (using <$>
and <*>
) as "lifting" function application so it works on functors as well. If you mentally ignore <$>
and <*>
it looks quite a lot like normal function application!
Applicative style is useful whenever you have a pure function and you want to give it impure arguments (or any functor arguments, really) -- basically when you want to do what you specified in your question!
The type signature of <$>
is
(<$>) :: Functor f => (a -> b) -> f a -> f b
which means it takes a pure function (in this case Node
) and a functor value (in this case numberNode x
) and it creates a new function wrapped "inside" a functor. You can add further arguments to this function with <*>
, which has the type signature
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
As you can see, this is very similar to <$>
only it works even when the function is wrapped "inside" a functor.
I'd like to add to the posts about Applicative above..
Considering the type of <$>
:
(<$>) :: Functor f => (a -> b) -> f a -> f b
it looks just like fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
which is also very much like Control.Monad.liftM:
liftM :: Monad m => (a -> b) -> m a -> m b
I think of this as "I need to lift the data constructor into this type"
On a related note, if you find yourself doing this:
action >>= return . f
you can instead do this:
f `fmap` action
The first example is using bind to take the value out of whatever type action is, calling f with it, and then repacking the result. Instead, we can lift f so that it takes the type of action as its argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With