Programación Funcional

Anuncio
Programación Funcional
Alberto Pardo
Marcos Viera
Instituto de Computación, Facultad de Ingenierı́a
Universidad de la República, Uruguay
Alberto Pardo, Marcos Viera
Programación Funcional
Mónadas
Modelado de efectos computacionales a través de mónadas.
Ejemplos de efectos:
Entrada-salida
Estado
No determinismo
Fallas
Excepciones
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador de Expresiones
data Exp = Num Int | Add Exp Exp
eval
:: Exp → Int
eval (Num n) = n
eval (Add x y ) = eval x + eval y
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Fallas
Supongamos que deseamos agregar un operador de división a
nuestras expresiones:
data Exp = Num Int | Add Exp Exp | Div Exp Exp
La operación de división debe controlar ahora el caso excepcional
de división por cero.
data Maybe a = Just a | Nothing
divM
:: Int → Int → Maybe Int
a ‘divM‘ b = if b ≡ 0 then Nothing
else Just (a ‘div ‘ b)
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Fallas (2)
eval
:: Exp → Maybe Int
eval (Num n) = Just n
eval (Add x y ) = case eval x of
Nothing → Nothing
Just a → case eval y of
Nothing → Nothing
Just b → Just (a + b)
eval (Div x y ) = case eval x of
Nothing → Nothing
Just a → case eval y of
Nothing → Nothing
Just b → a ‘divM‘ b
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Fallas (3)
Definamos:
return :: a → Maybe a
return a = Just a
(>>=) :: Maybe a → (a → Maybe b) → Maybe b
m >>= f = case m of
Nothing → Nothing
Just a → f a
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Fallas (4)
Entonces,
eval
:: Exp → Maybe Int
eval (Num n) = return n
eval (Add x y ) = eval x >
>= λa →
eval y >
>= λb →
return (a + b)
eval (Div x y ) = eval x >
>= λa →
eval y >
>= λb →
a ‘divM‘ b
Alberto Pardo, Marcos Viera
Programación Funcional
La clase Monad
class Monad m where
(>>=) :: m a → (a → m b) → m b
(>>) :: m a → m b → m b
return :: a → m a
fail
:: String → m a
m >> k = m >>= \ → k
fail s = error s
Alberto Pardo, Marcos Viera
Programación Funcional
Mónada Maybe
data Maybe a = Just a | Nothing
instance Monad Maybe where
return = Just
m >>= k = case m of
Just x → k x
Nothing → Nothing
fail
= Nothing
Alberto Pardo, Marcos Viera
Programación Funcional
Leyes de mónadas
return x >>= f
= f x
m >>= return = m
(m >>= f ) >>= g
= m>
>= λx → (f x >>= g )
Alberto Pardo, Marcos Viera
Programación Funcional
Composición de funciones monádicas
(•) :: Monad m ⇒ (b → m c) → (a → m b) → a → m c
(f • g ) a = g a >
>= f
Propiedades:
f • return = f
return • f
= f
(f • g ) • h = f • (g • h)
Se prueban facilmente usando las leyes de mónadas.
Alberto Pardo, Marcos Viera
Programación Funcional
Notación do
do m
=m
do {x ← m; m0 } = m >
>= λx → do m0
do {m; m0 }
=m>
> do m0
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Fallas (notación do)
eval :: Exp → Maybe Int
eval (Num n) = return n
eval (Add x y ) = do a ← eval x
b ← eval y
return (a + b)
eval (Div x y ) = do a ← eval x
b ← eval y
a ‘divM‘ b
Alberto Pardo, Marcos Viera
Programación Funcional
Mónada Exception
data Exceptional e a = Success a | Exception e
instance Monad (Exceptional e) where
return
= Success
Exception e >>= = Exception e
Success a >>= f = f a
throw :: e → Exceptional e a
throw = Exception
catch :: Exceptional e a → (e → Exceptional e a) → Exceptional e a
catch (Exception e) h = h e
catch (Success a)
= Success a
Alberto Pardo, Marcos Viera
Programación Funcional
Funciones sobre Mónadas (ver Control.Monad)
sequence
:: Monad m ⇒ [m a] → m [a]
sequence [ ]
= return [ ]
sequence (m : ms) = do x ← m
xs ← sequence ms
return (x : xs)
filterM
:: (Monad m) ⇒ (a → m Bool) → [a] → m [a]
= return [ ]
filterM [ ]
filterM p (x : xs) = do b ← p x
ys ← filterM p xs
return (if b then x : ys else ys)
Alberto Pardo, Marcos Viera
Programación Funcional
Funciones sobre Mónadas (ver Control.Monad)
addM :: (Num a, Monad m) ⇒ m a → m a → m a
addM m m0 = do x ← m
y ← m0
return (x + y )
liftM2 :: (a → b → c) → m a → m b → m c
liftM2 f m m0 = do x ← m
y ← m0
return (f x y )
addM = liftM2 (+)
Alberto Pardo, Marcos Viera
Programación Funcional
Mónada List - No Determinismo
Computaciones que pueden retornar 0, 1 o más resultados.
instance Monad [ ] where
return x = [x ]
m >>= f = concat (map f m)
fail
= []
Por ejemplo, sumar dos computaciones que pueden tener dos
posibles valores:
sumaL = do x ← [1, 2]
y ← [3, 4]
return (x + y )
Resulta en [4, 5, 5, 6]
Alberto Pardo, Marcos Viera
Programación Funcional
Mónada Reader
Computaciones que lee valores de un ambiente compartido.
newtype Reader e a = Reader {runReader :: (e → a)}
instance Monad (Reader e) where
return a
= Reader $ λe → a
(Reader r ) >>= f = Reader $ λe → runReader (f (r e)) e
ask :: Reader e e
ask = Reader id
local :: (e → e) → Reader e a → Reader e a
local f c = Reader $ λe → runReader c (f e)
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Variables
data Exp = · · · | Var ID | Let ID Exp Exp
eval :: Exp → Reader (Map ID Int) Int
eval (Num n) = return n
eval (Add e e 0 ) = do a ← eval e
b ← eval e 0
return (a + b)
eval (Var v )
= do s ← ask
return (fromJust $ lookup v s)
eval (Let v e b) = do a ← eval e
local (insert v a) (eval b)
Alberto Pardo, Marcos Viera
Programación Funcional
Mónada de estado
Computaciones que mantienen un estado
newtype State s a = State {runState :: s → (a, s)}
instance Monad (State s) where
return a = State $ λs → (a, s)
m >>= f = State $ λs → let (a, s 0 ) = runState m s
in runState (f a) s 0
get = State $ λs → (s, s)
put s = State $ \ → ((), s)
Alberto Pardo, Marcos Viera
Programación Funcional
Evaluador con Estado
data Exp = · · · | Var ID | Assign ID Exp
eval :: Exp → State (Map ID Int) Int
eval (Num n)
= return n
0
eval (Add e e ) = do a ← eval e
b ← eval e 0
return (a + b)
eval (Var v )
= do s ← get
return (fromJust $ lookup v s)
eval (Assign v e) = do a ← eval e
s ← get
put (insert v a s)
return a
Alberto Pardo, Marcos Viera
Programación Funcional
Descargar