Marcelo Camargo
Systems analyst, translator & programming languages researcher
Monads, monoids and functors
marcelocamargo@linuxmail.org
github.com/haskellcamargo
Index
1. Computations may fail
2. Concepts and definitions
3. Using monads to solve problems
4. Conclusion
1. Computations may fail
var head = function(list) {
return list[0];
}
head :: [a] -> a
head (x:_) = x
main :: IO ()
main = print $ head []
NULL!?
Every time you returns null, a capybara dies
Ah, but, what can go wrong?
─ I/O operations
─ Non-exhaustive patterns
─ HTTP requests
2. Concepts and definitions
A MONAD IS JUST A MONOID
IN THE CATEGORY OF THE ENDOFUNCTORS
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
(m >> n) :: m >>= \_ -> n
Monoid
─ Algebraic structure
─ Fulfills identity principle (no-op)
0 + 7 == 7 + 0 == 7
[] ++ [1, 2, 3] == [1, 2, 3] ++ [] == [1, 2, 3]
{} union {apple} == {apple} union {} == {apple}
─ A set of objects and a way to join them
Functor
─ Work on a structure without touching it
─ Implements fmap
class Functor f where
fmap :: (a -> b) -> f a -> f b
-- Should obey
fmap id = id
fmap (p . q) = (fmap p) . (fmap q)
─ Category mapping
Endofunctor
─ Functor mapping A -> A
─ Also implements fmap
µ :: Monad m => m (m a) -> m a
─ So, monads are monoids and they fit in the category of the endofunctors
Monads?
Monads!
data Maybe = Just a | Nothing
> fmap (+3) (Just 2)
Just 5
instance Functor Maybe where
fmap func (Just val) = Just (func val)
fmap func Nothing = Nothing
fmap of function to function <$>
>>=
Thank you, Aditya Bhargava!
3. Using monads to solve problems
module IOExample where
-- Using binding, applying a monad
-- IO String and returning a monad IO ()
main :: IO ()
main = getLine >>= putStrLn
-- Using do-notation to simulate
-- imperative programming
main' :: IO ()
main' = do
line <- getLine
putStrLn line
module MaybeExample where
import Data.Maybe (fromJust)
-- Safe definition of
head' :: [a] -> Maybe a
head' [] = Nothing
head' (x:_) = Just x
failure :: [String]
failure = []
success :: [String]
success = ["eita"]
-- Safe and monadic usage of head
nop = return (head' failure) >>= putStrLn . show
op = return (head' success) >>= putStrLn . show
// findUser :: Integer -> Maybe { name :: String }
var findUser = function(id) { ... }
var handleUser = function(id) {
findUser(id)
.bind(user => {
console.log("Welcome, " + user + "!");
});
}
// findUser :: Integer -> Maybe { name :: String }
var findUser = function(id) { ... }
var handleUser = function(id) {
var user = findUser(id).def("Visitor");
console.log("Welcome, " + user + "!");
}
4. Conclusion
1. Computations may fail
2. Monads hold error-prone states
4. Monads are love <3