traduccion programacion monadas monada monad funtores functores haskell monads

haskell - programacion - monadas javascript



¿Cuáles son las definiciones para>>=y return para la mónada IO? (3)

No hacen nada especial y solo están ahí para secuenciar acciones. Sería útil si piensas en ellos con diferentes nombres:

>> = se convierte en "y luego, utilizando el resultado de la acción anterior"

>> se convierte en "y luego"

el retorno se convierte en "no hacer nada, pero el resultado de no hacer nada es"

Esto convierte esta función en:

main :: IO () main = putStr "hello" >> return " world" >>= putStrLn

se convierte en:

main :: IO () main = putStr "hello" and then, do nothing, but the result of doing nothing is " world" and then, using the result of the previous action, putStrLn

Al final, no hay nada mágico sobre IO. Es exactamente tan mágico como un punto y coma en C.

Después de ver cómo se definen las mónadas List y Maybe, naturalmente comencé a sentir curiosidad acerca de cómo se definen las operaciones >>= y return para la mónada IO.


No hay implementación específica para IO ; es un tipo abstracto, con la implementación exacta no definida por el Informe Haskell. De hecho, no hay nada que detenga una implementación implementando IO y su instancia de Monad como primitivas del compilador, sin ninguna implementación de Haskell.

Básicamente, Monad se usa como una interfaz para IO , que no puede implementarse solo en Haskell puro. Probablemente esto sea todo lo que necesita saber en esta etapa, y profundizar en los detalles de la implementación probablemente solo confunda, en lugar de dar una idea.

Dicho esto, si observas el código fuente de GHC, verás que representa IO a como una función que se parece a State# RealWorld -> (# State# RealWorld, a #) (usando una tupla unboxed como el tipo de devolución), pero esto es engañoso; es un detalle de implementación, y estos valores State# RealWorld no existen realmente en tiempo de ejecución. IO no es una mónada de estado, 1 en teoría o en práctica.

En cambio, GHC usa primitivas impuras para implementar estas operaciones de IO; los "valores" State# RealWorld son solo para detener las declaraciones de reordenamiento del compilador al introducir dependencias de datos de una declaración a la siguiente.

Pero si realmente quieres ver la implementación de return de GHC y (>>=) , aquí están:

returnIO :: a -> IO a returnIO x = IO $ / s -> (# s, x #) bindIO :: IO a -> (a -> IO b) -> IO b bindIO (IO m) k = IO $ / s -> case m s of (# new_s, a #) -> unIO (k a) new_s

donde unIO simplemente desenvuelve la función desde el interior del constructor de IO .

Es importante observar que IO a representa una descripción de un cálculo impuro que podría ejecutarse para producir un valor de tipo a . El hecho de que exista una forma de obtener valores de la representación interna de IH de GHC no significa que esto se cumpla en general, o que pueda hacer algo así con todas las mónadas. Es puramente un detalle de implementación por parte de GHC.

1 La mónada de estado es una mónada utilizada para acceder y mutar un estado a través de una serie de cálculos; se representa como s -> (a, s) (donde s es el tipo de estado), que se ve muy similar al tipo que GHC usa para IO , por lo tanto, la confusión.


Te decepcionará, pero >>= en IO mónada no es tan interesante. Para citar la fuente de GHC:

{- | A value of type @''IO'' a@ is a computation which, when performed, does some I//O before returning a value of type @a@. There is really only one way to /"perform/" an I//O action: bind it to @Main.main@ in your program. When your program is run, the I//O will be performed. It isn''t possible to perform I//O from an arbitrary function, unless that function is itself in the ''IO'' monad and called at some point, directly or indirectly, from @Main.main@. ''IO'' is a monad, so ''IO'' actions can be combined using either the do-notation or the ''>>'' and ''>>='' operations from the ''Monad'' class. -} newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))

Eso significa que la mónada IO se declara como la instancia de State mónada State State# y su >>= está definida allí (y su implementación es bastante fácil de adivinar) .

Ver IO dentro del artículo en la wiki de Haskell para más detalles sobre la mónada IO . También es útil consultar los documentos de Haskell , donde cada posición tiene un pequeño enlace de "Fuente" a la derecha.

Actualización: Y ahí va otra decepción, que es mi respuesta, porque no noté el ''#'' en State# . Sin embargo, IO comporta como una mónada de State lleva el estado abstracto de RealWorld

Como @ehird escribió State# es el compilador interno y >>= para IO GHC.Base se define en el módulo GHC.Base :

instance Monad IO where {-# INLINE return #-} {-# INLINE (>>) #-} {-# INLINE (>>=) #-} m >> k = m >>= / _ -> k return = returnIO (>>=) = bindIO fail s = failIO s returnIO :: a -> IO a returnIO x = IO $ / s -> (# s, x #) bindIO :: IO a -> (a -> IO b) -> IO b bindIO (IO m) k = IO $ / s -> case m s of (# new_s, a #) -> unIO (k a) new_s