Monads are a design pattern to add "power-ups" to a value
Example: The "numberwang monad" - just a number, but with the "power-up" that it might also be numberwang
Numberwang is a British game show parody that follows concealed rules (wink, wink, like a monad):
Two things helped me understand what monads are about:
We really want to compose functions together Sometimes we can't compose functions together :( (because of type mismatches or uncertain values)Monads let us force square pegs in round holes so we can compose again :)
In more specific terms, monads let us preserve a "context" through code that doesn't handle said context.
- Programs are really just lots of values passed through lots of functions. If the wrong value goes into the wrong function, your program blows up. Monads let your program chug happily along without it even caring what specific values go through it.-- Step 1: define our numberwang type type Numberwang = Just Int | Numberwang Int toNumberwang : Int -> Numberwang toNumberwang i = case i of 4 -> Numberwang i -- if it's Tuesday or a leap year, and it's raining, and -- the number of letters in your name is a factorial of -- your guess, etc etc etc... -> Numberang i _ -> Just i -- > toNumberwang 2 -- Just 2 : Numberwang -- > toNumberwang 4 -- Numberwang 4 : Numberwang
-- Step 2: a function that knows nothing about numberwangs inc : Int -> Int inc i = i + 1 -- > inc 2 -- 3 : Int -- > inc (toNumberwang 2) -- Error: Function `inc` is expecting: Int, But received: Numberwang
-- Step 3: jamming a numberwang into our non-numberwang function magicSauce : Numberwang -> (Int -> Numberwang) -> Numberwang magicSauce n f = case n of Just i -> f i Numberwang i -> f i incNumberwang : Numberwang -> Numberwang incNumberwang n = magicSauce n (\i -> toNumberwang (inc i)) -- > incNumberwang (toNumberwang 2) -- Just 3 : Numberwang -- > incNumberwang (toNumberwang 4) -- Just 5 : Numberwang bruteForceNumberwang : Numberwang -> String bruteForceNumberwang n = case n of Numberwang i -> (toString i) ++ " -- That's numberwang!" _ -> bruteForceNumberwang (incNumberwang n) -- > bruteForceNumberwang (toNumberwang 0) -- "4 -- That's numberwang!" : String
Monads wrap uncertain data.
Wrapped data is considered tainted, but our code can still safely work with it thanks to monads, and the actual interactions with the uncertain aspects are quarantined to an single place in our code.
- This example is contrived and over simplified, but in the real world monads are more useful, and syntactic sugar makes monad composition simple and expressive. - By using monads in a pure functional language, you can actually mathematically prove that your program will work, no matter what data goes through it.Some resources I found most helpful:
http://blog.leahhanson.us/post/monad-tutorial.html http://blog.sigfpe.com/2007/04/trivial-monad.html https://www.quora.com/Why-dont-monads-violate-the-purely-functional-nature-of-languages http://learnyouahaskell.com/a-fistful-of-monads https://en.wikipedia.org/wiki/Monad_(functional_programming)
This presentation - http://jschomay.github.io/monad-wang