La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Programación monádica

Presentaciones similares


Presentación del tema: "Programación monádica"— Transcripción de la presentación:

1 Programación monádica
Las variaciones del evaluador tienen una estructura similar. Abstrayendo en esta estructura podemos introducir la noción de mónada: En cada variación introdujimos un tipo de computación, M digamos, donde M representa respectivamente computaciones que podrían levantar excepciones, actuar sobre un estado y generar salida. El evaluador original tiene tipo Term  Int, mientras que cada una de sus variaciones tiene tipo Term  M Int. En general, una función de tipo a  b es reemplazada por una función de tipo a  M b. Este tipo puede ser entendido como el de aquellas funciones que aceptan un argumento de tipo a y retornan un valor de tipo b, con un posible efecto lateral que es el que captura M.

2 Operaciones de M Qué clase de operaciones sobre M son requeridas?
Necesitamos una forma de transformar un valor en una computación que retorna ese valor y no efectúa ninguna otra acción: return :: a  M a Necesitamos aplicar una función de tipo a  M b a una computación de tipo M a : () :: M a  (a  M b)  M b Una mónada es una tripleta (M,return, ), que consiste de un constructor de tipos M y dos operaciones con los tipos polimórficos arriba presentados.

3 Operaciones de M (2) Composición de computaciones: Lectura:
m  \a -> n Lectura: Efectúe la computación m, ligue a al valor resultante y luego efectúe la computación n. Secuencia de computaciones: () :: M a  M b  M b Lectura de m  n: Efectúe la computación m y luego la computación n. Cómo definir  usando  ?

4 Mónadas en Haskell Las clases Monad, MonadZero y MonadPlus:
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 class (Monad M)  MonadZero M where zero :: M a class (MonadZero m)  MonadPlus m where (++) :: M a  M a  M a

5 La mónada Excepción En esta mónada una computación puede levantar una excepción o retornar un valor. data Exc a = Raise Exception | Return a type Exception = String instance Monad Exc where return x = Return x (Raise e)  q = Raise e (Return x)  q = q x return x simplemente retorna el valor x p  q examina el resultado de la computación p, si es una excepción entonces es re-levantada, sino la función q es aplicada al valor retornado.

6 Operaciones de Excepción
(no abstractas) raise :: Exception  Exc a raise = Raise (escape) :: Exc a  Exc a  Exc a (Raise _ ) escape n = n (Return x) escape n = Return x elim :: Exc a  (a  b)  (Exception  b)  b elim (Raise e) f g = g e elim (Return x) f g = f x (abstracta) updateError :: Exc a  Exception  Exc a updateError m str = elim m return (raise . (++ str))

7 Expresiones do La expresión do permite usar una sintaxis más legible para expresar programación monádica. Sintaxis Semántica (traducción al kernel) exp -> do { stmts [;]} stmts -> exp [; stmts] do {e} = e | pat  exp ; stmts do {e;stmts} = e  do {stmts} | let decllist ; stmts do {p  e ; stmts} = e = \p -> do{stmst} do {let decllist; stmts} = let decllist in do{stmts}

8 Un Evaluador Monádico El evaluador es ahora escrito usando una mónada m: eval :: Monad m  Term  m Int eval (Con x) = return x eval (Div t u) = do x  eval t y  eval u return (x div y) El tipo de eval indica que esta función dado un Term efectúa una computación m y retorna un valor de tipo Int. La estructura de este evaluador es un poco más compleja que la del original, pero es más flexible: cada una de las variaciones discutidas puede ser obtenida fácilmente.

9 El evaluador original En este evaluador la computación es simplemente el valor retornado. Introducimos entonces la monad identidad: newtype Id  = MkId  instance Monad Id where return x = MkId x (MkId x)  q = q x Id es isomorfo a la función identidad de tipos return es isomorfo a la función identidad  es isomorfo a la aplicación de funciones instance Show   Show (Id ) where show (MkId x) = “value: “ ++ show x evalId :: Term  Id Int evalId = eval

10 Manejo de errores Para agregar manejo de errores tomamos el evaluador monádico y reemplazamos el término return (x div y) por una expresión condicional. evalEx :: Term  Exc Int evalEx (Con x) = return x evalEx (Div t u) = do x  evalEx t y  evalEx u if y == 0 then raise “division by zero” else return (x div y)

11 Estado En la mónada estado, una computación acepta un estado inicial y retorna una pareja consistente de un valor y el estado final. instance Monad St where return x = MkSt f where f = \s -> (x,s) p  q = MkSt f where f = \s -> apply (q x) s’ where (x,s’) = apply p s return x retorna el transf. de estado que devuelve el valor x y deja incambiado el estado. una llamada a p  q aplica el transf. p al estado inicial s, lo que retorna un valor x y el estado intermedio s’. Luego, el transf. q x es aplicado a s’.

12 Contando ejecuciones Una operación específica de la monad St es:
tick :: St () tick = MkSt f where f = \s -> ((), s + 1) Para agregar conteo de ejecuciones tomamos el evaluador monádico y sólo agregamos una llamada a tick en el lugar adecuado. evalSt :: Term  St Int evalSt (Con x) = return x evalSt (Div t u) = do x  evalSt t y  evalSt u tick return (x div y)

13 Salida En la monad de salida una computación consiste en el par formado por la salida generada y el valor final. instance Monad Out where return x = MkOut (“”, x) p  q = MkOut (ox ++ oy, y) where MkOut (ox,x) = p MkOut (oy, y) = q x return x retorna el par que consiste en la salida vacía y el valor x p  q extrae una salida ox y el valor x a partir de la computación p, luego extrae una salida oy y el valor y del resultado de la computación q, y finalmente devuelve la salida formada por la concatenación de ox y oy y el valor final y.

14 Desplegando trazas de ejecución
Una operación específica de la mónada Out es: out :: Output  Out () out ox = MkOut (ox, ()) Para agregar trazas de ejecución, decoramos al evaluador monádico original con las correpondientes llamadas para generar salida: evalOut :: Term  Out Int evalOut (Con x) = do {out (line (Con x) x) ; return x} evalOut (Div t u) = do x  evalOut t y  evalOut u let z = (x div y) out (line (Div t u)) z return z

15 Combinando estado con excepciones
module MonadStExc where import Exception data StE st a = MkStE (st  Exc (a , st)) applyStE :: Ste st a  st  Exc (a , st)) applyStE (MkStE f) st = f st instance Monad (StE st) where return a = MkStE (\s -> return (a,s)) (MkStE f)  g = MkStE h where h = \s -> do (a , s’)  f s applyStE (g a) s’

16 Operaciones de StE (no abstractas) (abstractas)
raiseStE :: Exception  StE st a raiseStE e = MkStE (\s -> raise e) getStE :: StE st st getStE = MkStE (\s -> return (s , s)) putStE :: st  StE st () putStE st = MkStE (\_ -> return (() , st)) (abstractas) updateStE :: (st  st)  StE st () updateStE f = getStE  (putStE . f) stripStE :: StE st a  st  Exc a stripStE f st = applyStE f s  (return . fst)


Descargar ppt "Programación monádica"

Presentaciones similares


Anuncios Google