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 mónada StateStateState# 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