Estoy ayudando a un amigo a aprender Haskell y recientemente creó un código como este, que revisa y produce un bucle de grabación de CPU en tiempo de ejecución. Estoy completamente desconcertado por esto.¿Por qué la importación de Control.Applicative permite que este código incorrecto escriba check?
import Control.Monad
import Control.Applicative
main = forever putStrLn "Hello, infinity"
Eso no debería escribir, pero sí. La versión correcta sería claramente:
main = forever $ putStrLn "Hello, infinity"
Lo raro y sorprendente para mí es que se obtienen diferentes resultados con y sin importar Control.Applicative. Sin importar que, no tipo de comprobación:
Prelude Control.Monad> forever putStrLn "Hello, infinity"
<interactive>:1:1:
No instance for (Monad ((->) String))
arising from a use of `forever'
Possible fix: add an instance declaration for (Monad ((->) String))
In the expression: forever putStrLn "Hello, infinity"
In an equation for `it': it = forever putStrLn "Hello, infinity"
no veo una instancia de Monad para ((->) String
en la fuente para Control.Applicative, así que supongo que está ocurriendo algo raro debido a su uso de Control.Category o Control.Arrow, pero no sé. Así que supongo que tengo dos preguntas:
- ¿Qué pasa con la importación de Control.Applicative que permite que esto suceda?
- ¿Qué sucede cuando ingresa al bucle infinito? ¿Qué está tratando de ejecutar Haskell en ese caso?
Gracias,
¿Puede explicar en qué es útil la instancia de '(->) e'? –
@DanielLyons Es útil cuando tiene muchas funciones que necesitan acceso a información de configuración compartida. Luego puede escribir (por ejemplo) 'foo >> = bar >> = baz' en lugar de repetir el entorno en todas partes como en' \ e -> let x = foo e; y = barra x e; z = baz y e en y'. –