Estoy desconcertado. Puedo escribir esto:Plegable, composición de funciones, mónadas y pereza, ¿verdad?
import Control.Monad
main = print $ head $ (foldr (.) id [f, g]) [3]
where f = (1:)
g = undefined
y la salida es 1
. Esto tiene sentido, ya que se reduce a:
main = print $ head $ ((1:) . undefined . id) [3]
main = print $ head $ (1:) ((undefined . id) [3])
main = print $ head $ 1 : ((undefined . id) [3])
main = print $ 1
Pero si uso una técnica monádico vagamente similar, que no funciona de la misma:
import Control.Monad
main = print $ (foldr (<=<) return [f, g]) 3
where f = const Nothing
g = undefined
Esto golpea prelude.Undefined
. Lo cual es extraño, porque yo esperaría que reducir:
main = print $ ((const Nothing) <=< undefined <=< return) 3
main = print $ return 3 >>= undefined >>= (\_ -> Nothing)
main = print $ Nothing -- nope! instead, undefined makes this blow up
Sin embargo, cambiando el orden de composición:
import Control.Monad
main = print $ (foldr (>=>) return [f, g]) 3
where f = const Nothing
g = undefined
Qué logra el cortocircuito esperada y produce Nothing
.
main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing
supongo que la comparación de los dos enfoques que podría haber sido comparar manzanas y naranjas, pero se puede explicar la diferencia? Pensé que f <=< g
era el análogo monádico de f . g
, pero aparentemente no son tan análogos como pensaba. ¿Puedes explicar porque?