1 / 16

Programación monádica

Programación monádica. Las variaciones del evaluador tienen una estructura similar. Abstrayendo en esta estructura podemos introducir la noción de mónada :

kale
Download Presentation

Programación monádica

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 MInt. • En general, una función de tipo a b es reemplazada por una función de tipoa Mb. 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 Ma • Necesitamos aplicar una función de tipo a Mb a una computación de tipo M a : • () :: M a(a Mb)  M b • Una mónada es una tripleta (M,return, ), que consistede un constructor de tipos M y dos operaciones con los tipos polimórficos arriba presentados.

  3. Operaciones de M (2) Composición de computaciones: m  \a -> n Lectura: Efectúe la computación m, ligue a al valor resultantey luego efectúe la computación n. Secuencia de computaciones: () :: M aMb  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 Ma () :: M a(a Mb)  M b () :: MaMb  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ónadam: 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 • Ides 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) = dox  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) 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)

More Related