The Monad is a simple and powerful abstraction, yet often considered complex and hard to understand. I'll discuss monads from a practical perspective and give a hands-on intro to the Haskell language and typeclasses. Then everyone gets to build some monads in Haskell.
Bring your own Haskell compilers! But don't worry, you can do this online too with one of these alternatives.
- https://www.fpcomplete.com/new-project
- http://www.compileonline.com/compile_haskell_online.php
- http://haskellonline.org/
My presentation can be viewed here. See presentation directory for more details.
There are 4 little excercises we do during the presentation. Solutions to those can be found here.
After the presentation, I'll present you with a bunch of challenges. I hope you'll be able to complete as many as possible. If you need help, want to review your solution or just lazy, you'll find ready-made solutions here.
Other material you might find useful and fun:
- Monad laws
- Functors, Applicatives and Monads in Pictures by Aditya Bhargava
Work hard and have fun!
- ghci
- Load source code
:l <filename>
- Reload source code
:r
- Type signature of expression
:t map reverse ["bacon", "eggs"]
- Info on function
:i map
or on typeclass:i Monad
- Import module
import Control.Applicative
- Load source code
- Hoogle
- search by function name:
map
or>>=
- search by type signature:
(a -> b) -> m a -> m b
- search by function name:
- Learn You a Haskell for Great Good
- Free book online
- Order a paper copy!
Bunch of Haskell monad examples that came to my mind.
All side-effects, including variable creation and access, are performed in the IO Monad. This allows you to keep your code predictable: you know what functions have side-effects and what don't.
STM is awesome. Haskell STM is even more awesome as you'll get type-level guarantee that your STM operations are actually reversible.
In the Snap framework, your handler code operates in the Snap Monad. This means that you get implicit
access to request and response state. You can also perform any IO using liftIO
function (a common practicse
in fact, using the MonadIO typeclass). Unlike ThreadLocals and such, you'll get a type-level guarantee that you
don't accidentally call Snap-dependent code from a "non handler thread". This is of course not the only neat
thing about Snap.
As in my haskell-transactional experiment, you can use a Monad to deal with database transactions in a really cool way. You'll get type-level guarantee that code that needs a database connection is only called in a context where such is available. Without passing the connection around. Commit/rollback is automatic too, of course.
As in my async experiment, you can use an Async monad (a.k.a Continuation Monad) to wrap any asynchronous operations. Then use the same do-notation for doing your async stuff as you use for your normal IO code.
There's no way a Haskell dev would use explicit callbacks like we do on Node.js. It's just too easy to abstract away.
Async, pausable, logging, distributed, transactional, whatnot. Stuff is really easy to wrap into a Monad. Abstract away the nasty implementation details and enjoy the beautiful monadic awesomeness.
You can re-use a lot of generic library code on any Monad. You get to use the nice do-notation that makes complex monadic code much easier to write and read. You know, List and Maybe are Monads too.