More example if you wish.
With some more operators.
Explaining Monad
This tutorial/ guidance/ article is one of some parts.
-
Overview: Summary.
-
References: About Monad.
-
Examining Bind: Bind
>>=
operator. Hello World Example. -
Examining Bind:
<*>
and<$>
operators. Personal Notes. Example using Number. -
Monadic Operator: Fish
>=>
operator.
The first one is overview, then some references. The last three parts is all about Example Code.
How does Monad works
I found good explanation about these three magic words (functor, applicative, and monad), using boxing analogy. I really respect the reader on how he made everything clear by putting some funny image on his article.
There’s a caveat in boxing analogy.
I did this note based on adit
works.
But since, it has some differences, with some additional notes also.
I decide to make my own article.
Context: Maybe, Just and Nothing
Haskell has context that can be wrapped around data type.
Maybe
, Just
and Nothing
.
This context approach solved common null value issue.
Now a data Maybe contain Nothing or Just a value.
data Maybe a = Nothing | Just a
deriving (Eq, Ord)
Consider open GHCI
and do some Math.
>3 * 5
15
>:t 3
3 :: Num t => t
Compare with plain data above, now we can wrap data in a context.
>Just 3
Just 3
>Nothing
Nothing
>:t Just 3
Just 3 :: Num a => Maybe a
>:t Nothing
Nothing :: Maybe a
>3 * Just 5
<interactive>:20:1: error:
>Just 3 * 5
<interactive>:21:1: error:
Just
is just a wrapper. Do not forget the bracket.
Bare unwrapped
Consider this Prelude using application operator and its reverse.
>(*3) 5
15
>(const 2) $ (*3) 5
2
>((const 2) . (*3)) 5
2
>5 (*3)
<interactive>:4:1: error:
>import Data.Function
Prelude Data.Function> (*3) 5 & (const 2)
2
Function is left associative. Apply left bare function to the bare value right.
Functor
How do we suppose to do simple thing with data context?
Here comes the <$>
operator in rescue.
>(*3) <$> (Just 5)
Just 15
>(const 2) <$> (*3) <$> (Just 5)
Just 2
>(const 2) <$> (*3) <$> [1..5]
[2,2,2,2,2]
>(id) <$> (*3) <$> [1..5]
[3,6,9,12,15]
>(Just 5) <$> (*3)
<interactive>:2:2: error:
>2 <$ [1..5]
[2,2,2,2,2]
Prelude Data.Functor> [1..5] $> 2
[2,2,2,2,2]
<$>
is left associative.
Apply left bare function to the wrapped context right.
Lists are functors.
We can rewrite it using fmap
alias,
or special map
for list.
fmap
is a generalisation of map
.
map
is a specialization of fmap
.
>(*3) <$> [1..5]
[3,6,9,12,15]
>fmap (*3) [1..5]
[3,6,9,12,15]
>map (*3) [1..5]
[3,6,9,12,15]
Function are Functor too. It looks like magic, but it is not.
>(const 2) <$> (*3) <$> Just 5
Just 2
>twofunc = (const 2) <$> (*3)
>twofunc 5
2
>twofunc Just 5
<interactive>:11:1: error:
Applicative
How about also wrapping the left function ?
Here comes the <*>
operator.
>Just (*3) <*> Just 5
Just 15
>pure (*3) <*> Just 5
Just 15
>Just 5 <*> Just (*3)
<interactive>:3:1: error:
<*>
is also left associative.
Apply left wrapped function to the context right.
>Just (*3) *> Just 5
Just 5
>Just (const 2) <*> Just (*3) <*> (Just 5)
<interactive>:20:1: error:
Using List
>[(*3), (const 2)] <*> [1..5]
[3,6,9,12,15,2,2,2,2,2]
Wrapping, in Functor and Applicative
Using boxing analogy.
While <$>
wrapped the value.
The <*>
also wrapped the function.
>(*3) <$> Just 5
Just 15
>fmap (*3) Just 5
Just 15
>Just (*3) <*> Just 5
Just 15
In context
>(*3) <$> Just 5
Just 15
>(*3) <$> Nothing
Nothing
>Just (*3) <*> Nothing
Nothing
>Nothing <*> Just 5
Nothing
>Nothing <$> Just 5
<interactive>:22:1: error:
Go further with both.
>(*) <$> (Just 3) <*> (Just 5)
Just 15
>min <$> (Just 3) <*> (Just 5)
Just 3
Bind
Apply it to bind.
> add3 int = [int + 3]
> [1, 3] >>= add3
[4,6]
And chain ‘em.
> addme int2 int1 = [int1 + int2]
> subme int2 int1 = [int1 - int2]
> [1, 3] >>= addme 3 >>= subme 2
[2,4]
> [1, 3] >>= subme 2 >>= addme 3
[2,4]
Rewrite the last sentence in multiline GHCI.
> :{
| addme int2 int1 = [int1 + int2]
| subme int2 int1 = [int1 - int2]
|
| sequ3 :: [Int]
| sequ3 =
| [1, 3]
| >>= subme 2
| >>= addme 3
| :}
> print sequ3
[2,4]
And finally in do
block.
> :{
| sequ4 :: [Int]
| sequ4 = do
| x <- [1, 3]
| y <- subme 2 x
| addme 3 y
| :}
> sequ4
[2,4]
Operator Cheat Sheet
Bear in mind
-
$
function application -
.
function composition -
<$>
fmap
as an infix operator.`fmap`
. -
<*>
Applicative -
(<$>) :: Functor f => (a -> b) -> f a -> f b
-
(<$>) = fmap
-
fmap :: Functor f => (a -> b) -> f a -> f b
-
map :: (a -> b) -> [a] -> [b]
-
(<*>) :: f (a > b) -> f a -> f b
Bear in mind.
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
instance Monad Maybe where
Nothing >>= func = Nothing
Just val >>= func = func val
More in this blog.
Further Explanation.
Meanwhile. Consider go back to adit
Thank you for Reading.


Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
Archives
- December 2017
- August 2017
- July 2017
- June 2017
-
May 2017
- Examining Bind in Haskell: Do Notation
- Examining Bind in Haskell: Hello World
- Explaining Monad: References
- Explaining Monad: Overview
- Loop in Haskell With Map, Part Three
- Loop in Haskell With Map, Part Two
- Loop in Haskell With Map, Part One
- Loop in Haskell With Map, Overview
- Modularized HerbstluftWM in Haskell
- Modularized HerbstluftWM in Lua
- Modularized HerbstluftWM in PHP
- Modularized HerbstluftWM in Ruby
- Modularized HerbstluftWM in Python
- Modularized HerbstluftWM in Perl
- Modularized HerbstluftWM in BASH
- Modularized HerbstluftWM Overview
- April 2017