Foncteurs & Applicatifs
-
Donnez la déclaration d'instance qui permet de faire du type fonction partiellement appliquée `(a ->)` un foncteur
instance Functor ((->) a) where
fmap :: (b -> c) -> (a -> b) -> (a -> c)
fmap = (.)
Commencer par écrire le type de `fmap` et regarder si une fonction du prélude a cette signature
-
Donnez la déclaration d'instance qui permet de faire de ce même type un applicatif
instance Applicative ((->) a) where
pure :: b -> (a -> b)
pure = const
(<*>) :: (a -> b -> c) -> (a -> b) -> (a -> c)
g <*> h = \x -> g x (h x)
Monades
Soit le type d'expression suivant : `data Exp a = Var a | Val Int | Add (Exp a) (Exp a)`
-
Faire de `Exp a` un foncteur.
instance Functor Exp where
fmap :: (a -> b) -> Exp a -> Exp b
fmap _ (Val n) = Val n
fmap f (Var x) = Var (f x)
fmap f (Add x y) = Add (fmap f x) (fmap f y)
ghci> let exp1 = Add (Var 3) (Var 5)
ghci> (*2) <$> exp1
Add (Var 6) (Var 10)
-
Faire de `Exp a` un applicatif.
instance Applicative Exp where
pure :: a -> Exp a
pure = Var
(<*>) :: Exp (a -> b) -> Exp a -> Exp b
Var f <*> e = f <$> e
Val n <*> _ = Val n
Add x y <*> e = Add (x <*> e) (y <*> e)
ghci> let expFunc = Add (Var (*2)) (Var (+1))
ghci> let expVal = Add (Var 3) (Var 5)
ghci> expFunc <*> expVal
Add (Add (Var 6) (Var 10)) (Add (Var 4) (Var 6))
-
Faire de `Exp a` une monade.
instance Monad Exp where
return :: a -> Exp a
return = pure
(>>=) :: Exp a -> (a -> Exp b) -> Exp b
Val n >>= _ = Val n
Var x >>= f = f x
Add x y >>= f = Add (x >>= f) (y >>= f)
ghci> let exp2 = Add (Var 3) (Val 5)
ghci> f x = Add (Var (x + 1)) (Val 2)
ghci> exp2 >>= f
Add (Add (Var 4) (Val 2)) (Val 5)