-
Notifications
You must be signed in to change notification settings - Fork 5
Notes for Week 15 Monads Part 1
Given that we have Functors and Applicative Functors, what additional benefit do Monads give us?
Monads are Applicative Functors. List all available methods on a Monadic instance.
import qualified Data.Monoid as M
lessThanHundred :: Int -> Maybe Int
lessThanHundred x =
isEven :: Int -> Maybe Int
isEven x =
complete :: Maybe String
complete = (return "complete")
valid = 20 :: Int
invalid = 25 :: Int
withDo :: Int -> Maybe String
withDo value =
pipeline :: Int -> Maybe String
pipeline value =
testValidWithPipeline = pipeline valid == complete
testInvalidWithPipeline = pipeline invalid == Nothing
testValidWithDo = withDo valid == complete
testInvalidWithDo = withDo invalid == Nothing
testAll = (M.getAll $ M.mconcat $ map M.All [testValidWithPipeline, testInvalidWithPipeline, testValidWithDo, testInvalidWithDo]) == True
Given the above functions:
Write the implementations of the lessThanHundred, isEven, withDo and pipeline functions such that:
- Any value that is less than a hundred and is even should result in the pipeline function returning Just "complete".
- Any value that is either greater than a hundred or odd should result in the pipeline function returning Nothing.
The withDo function should use the "do" syntax and the pipeline method should use monadic functions. Essentially they return the same result but use different syntaxes.
Use the test* functions to verify your individual functions and the testAll function to verify all tests.
//TODO
For a start, monads are functors and applicative functors. A monad is a monoid in a category of endo functions (functions that take and give the same type), with unit as the join as the binary operation.
"If we have a value with a context, m a, how do we apply to it a function that takes a normal a and returns a value with a context? In other words, how do we apply a function of type a -> m b to a value of type m a?"
Allows us to lift a function up into a computational context. Monads add bind function to applicative functions.
return - takes something and wraps it in a monad. Same as pure.
= - bind takes a monadic value, to a function and returns a monadic value.
- evaluate to unit or to the right hand value. fail - called when pattern matching fails.
import Data.Char
import Data.List
import Data.Monoid
import Data.Foldable
import qualified Data.Monoid as M
lessThanHundred :: Int -> Maybe Int
lessThanHundred x = if (x < 100) then Just x else Nothing
isEven :: Int -> Maybe Int
isEven x = if (x `mod` 2 == 0) then Just x else Nothing
complete :: Maybe String
complete = (return "complete")
valid = 20 :: Int
invalid = 25 :: Int
withDo :: Int -> Maybe String
withDo value = do
x <- isEven value
_ <- lessThanHundred x
complete
pipeline :: Int -> Maybe String
pipeline value =
isEven value >>= (\x ->
lessThanHundred x >>= (\_ ->
complete))
Bret Victor on a better programming environment:
- http://www.i-programmer.info/news/112-theory/3900-a-better-way-to-program.html (links to the full talk)
- http://www.youtube.com/watch?v=PlI-gPu3SPI (just the game programming)
- http://markdblackwell.blogspot.com.au/2012/03/bret-victor-inventing-on-principle.html (notes)
What a Monad is not
...and while addition and multiplication are both monoids over the positive natural numbers, an oven is a monoid over food (Burned pizza doesn't concern us, here: Food stays food, even if you don't want to eat it.), a monad is a monoid object in a category of endofunctors: return is the unit, and join is the binary operation. It couldn't be more simple. If that confuses you, it might be helpful to see a Monad as a lax functor from a terminal bicategory.
Monad operations (bind and return) have to be non-strict in fact, always!
Instead, every monad is an applicative functor (as well as a functor). It is considered good practice not to use >>= if all you need is <*>, or even fmap.
Monads are commonly used to order sequences of computations. But this is misleading. Just as you can use monads for state, or strictness, you can use them to order computations. But there are also commutative monads, like Maybe, that don't order anything. So ordering is not in any way essential to what a monad is.