una que programacion mónadas monadas monada funtores functores funcional ejemplos dividir aplicativos haskell get put state-monad

que - Haskell: intentando desugar la simple mónada de estado ponerse y ponerse



que es una monada programacion funcional (1)

Para estudiar los detalles de la mónada de estado, estoy tratando de crear una versión completa desambiguada de una función de mónada de estado simple, completando el pensamiento iniciado en ¿Cómo ''obtener'' realmente / obtener / el estado inicial en Haskell? , en la respuesta de J Cooper.

La función de mónada de estado de ejemplo simplemente intercambia el estado y el valor de entrada, de modo que (conceptualmente) si la entrada es (v, s), entonces la salida es (s, v). Muestro tres traducciones, primero de notación do a desagrupado >> = y >>, luego colocando esos operadores en posición de función, y finalmente intentando reemplazarlos y poner / poner con sus definiciones.

La versión ''do'' y las primeras dos traducciones funcionan, pero la traducción final no. Problemas:

  1. Al cargar el módulo, GHCi informa que z1 no está dentro del alcance.
  2. No he resuelto exactamente cómo representar omitir el argumento que pasa en la >> traducción.

¿Cómo deberían ser arreglados?

FWIW, plataforma Haskell actual (GHC 7.4.2).

¡Gracias!

-- simpleswap import Control.Monad.State -- ============================================= -- ''Do'' version simpleswap1 :: String -> State String String simpleswap1 inp = do z1 <- get put inp return z1 -- ============================================= -- Desugared to >>= and >> simpleswap2 :: String -> State String String simpleswap2 inp = get >>= /z1 -> put inp >> return z1 -- ============================================= -- >>= and >> changed to function position simpleswap3 :: String -> State String String simpleswap3 inp = (>>=) get (/z1 -> (>>) (put inp) (return z1) ) -- ============================================= -- Attempt to translate >>=, >>, get and put simpleswap4 :: String -> State String String simpleswap4 inp = state $ /s1 -> -- (>>=) let (a2, s2) = runState ( {- get -} state $ /sg -> (sg,sg) ) s1 in runState (rhs1 a2) s2 where rhs1 a2 = /z1 -> -- (>>) state $ /s3 -> let (a4, s4) = runState ( {- put inp -} state $ /_ -> (inp, ()) ) s3 in runState (rhs2 a4) s4 where rhs2 a4 = return z1 -- ============================================= main = do putStrLn "version 1004" let v = "vvv" let s = "sss" putStrLn ("Before val: " ++ v ++ " state: " ++ s) let (v2, s2) = runState (simpleswap4 v) s putStrLn ("After val: " ++ v2 ++ " state: " ++ s2) -- =============================================


Hay algunos errores menores en simpleswap4 . Aquí hay una versión corregida:

simpleswap4 :: String -> State String String simpleswap4 inp = state $ /s1 -> -- (>>=) let (z1, s2) = runState ( {- get -} state $ /sg -> (sg,sg) ) s1 in runState (rhs1 z1) s2 where rhs1 z1 = -- (>>) state $ /s3 -> let (_, s4) = runState ( {- put inp -} state $ /_ -> ((), inp) ) s3 in runState rhs2 s4 where rhs2 = return z1

a2 nombre de a2 a z1 (en las líneas 5 y 6). Esto no cambia la semántica, pero enfatizó que el primer componente del par devuelto por la llamada get desacralizada es en realidad el resultado que se une a z1 en las versiones anteriores de simpleswap .

El tipo de rhs1 debe ser String -> State String String . En su versión, obtiene una variable adicional vinculada a lambda. No está claro cuál debería ser la diferencia entre a2 y z1 en su versión. La eliminación de la lambda (en la línea 8) también tiene la ventaja de solucionar su problema de alcance. Está utilizando z1 en la cláusula- where anidada, pero where solo puede ver variables vinculadas en el lado izquierdo de la declaración a la que está adjuntado.

En la línea 11, he reemplazado a4 con _ . Esto es para enfatizar que (>>) descarta el resultado de la primera acción. Como consecuencia, rhs2 tampoco se parametriza sobre este resultado.