Last active
May 20, 2020 15:54
-
-
Save expede/59b4e7e49fd394210ca5f31c7f00f382 to your computer and use it in GitHub Desktop.
Witchcraft Monadic Do Notation Primer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ======== | |
# NOTATION | |
# ======== | |
# Control.Monad (Haskell) Bind | |
>>= | |
# Witchcraft.Chain.bind (Elixir) | |
>>> | |
# ========== | |
# DESUGARING | |
# ========== | |
monad [] do | |
a <- [1] | |
b <- [2] | |
return(a + b) | |
end | |
# Same as | |
[1] >>> fn a -> | |
[2] >>> fn b -> | |
Witchcraft.Applicative.pure([], a + b) # <~ This is return(a + b) in the context of [] | |
end | |
end | |
# Same as | |
Witchcraft.Chain.bind([1], fn a -> | |
Witchcraft.Chain.bind([2], fn b -> | |
Witchcraft.Applicative.pure([], a + b) | |
end) | |
end) | |
# ========== | |
# LIST MONAD | |
# ========== | |
monad [] do | |
1 | |
end | |
#=> 1 | |
monad [] do | |
return 1 | |
end | |
#=> [1] | |
monad [] do | |
a <- [1, 2] | |
return a | |
end | |
#=> [1, 2] | |
# Strictly speaking, you don't need `return` at all! | |
monad [] do | |
a <- [1, 2] | |
[a] # Same as `return` in `[]` | |
end | |
#=> [1, 2] | |
monad [] do | |
a <- [1, 2, 3] | |
b <- [10, 100] | |
return(a * b) | |
end | |
#=> [10, 100, 20, 200, 30, 300] | |
# NOTE: length 2 x 3 (every element of `a` multiplied by every element of `b`) | |
monad [] do | |
a <- [1, 2, 3] | |
b <- [10, 100] | |
c <- return(a * b) # NOTE bind intermediate result to `c` | |
d <- [2, 4] | |
return(c + d) | |
end | |
#=> [20, 40, 200, 400, 40, 80, 400, 800, 60, 120, 600, 1200] | |
monad [] do | |
a <- [1, 2, 3] | |
b <- [10, 100] | |
c <- return(a * b) | |
return(a + b + c) # NOTE reusing `a` and `b` | |
end | |
#=> [21, 201, 32, 302, 43, 403] | |
# =========== | |
# MAYBE MONAD | |
# =========== | |
# @type Maybe.t :: %Just{just: any} | %Nothing{} | |
monad %Maybe.Just{} do | |
a <- %Just{just: 2} | |
b <- %Just{just: 10} | |
return(a * b) | |
end | |
#=> %Just{just: 20} | |
monad %Maybe.Just{} do | |
a <- %Just{just: 2} | |
b <- %Nothing{} | |
return(a * b) | |
end | |
#=> %Nothing{} | |
# ============================= | |
# DIRECT COMPARISION WITH MAYBE | |
# ============================= | |
# Note that the insides of both blocks are IDENTICAL, | |
# but do these operations "inside" if the wrapping type. | |
# Behaviour is "the same" as interpreted by each datatype. | |
monad [] do | |
a <- return(2) # [2] | |
b <- return(4) # [4] | |
return(a + b) | |
end | |
#=> [6] | |
monad %Maybe.Just{} do | |
a <- return(2) # %Just{just: 2} | |
b <- return(4) # %Just{just: 4} | |
return(a + b) | |
end | |
#=> %Just{just: 6} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment