6. Monads I
23/02/23
Refresh - Functor
-- f is a type like lists, tree
class Functor f where
fmap :: (a->b) -> f a -> f b -- f is a data structure
If already have a functor, can be an Applicative (using =>
). Have to follow a set of conditions using where
.
Applicative functors - captures a basic form or a basic pattern with affect.
Applicative style is pure functions applied to effect for arguments
Example: simple evaluator
data Expr = Val Int | Div Expr Expr
eval :: Expr -> Int
eval (Val n) = n
eval (Div x y) = eval x `div` eval y -- could crash if x/y is 0
Safediv
This is a safe version of div
safediv :: Int -> Int -> Maybe Int
safediv _ 0 = Nothing
safediv n m = Just (n `div` m)
Now rewrite Expr so it can use safediv
safediv :: Int -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = case eval x of
Nothing -> Nothing
Just n -> case eval y of
Nothing -> Nothing
Just m -> safediv n m
This function will never crash, however it is a bit complicated. But can simplify this further
eval :: Expr -> Maybe Int
eval (Val n) = pure n
eval (Div x y) = pure safediv (*) eval x (*) eval y -- Best, however this cause a type error
Safediv is not a pure function as it returns a maybe type
Template box
This is a case analyses on something ([BOX]
)
case [BOX] of
Nothing -> Nothing
Just x -> [BOX] x
Can turn this template into ->
mx >>= f = case mx of
Nothing -> Nothing
Just x -> f x
(>>=) :: Maybe a -> (a -> )
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = eval x >>= (\n ->
eval y >>= (\m ->
safediv n m)
>>=
is an into operator
do notation
As this occurs frequently, can use the do notation. Its like a syntax sugar.
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = do n <- eval x
m <- eval y
safediv n m