Sono perplesso. Posso scrivere questo:Pieghevole, composizione funzionale, monade e pigrizia, oh mio?
import Control.Monad
main = print $ head $ (foldr (.) id [f, g]) [3]
where f = (1:)
g = undefined
e l'uscita è 1
. Questo ha senso, perché si riduce 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
Ma se io uso una tecnica monadica vagamente simile, ma non funziona lo stesso:
import Control.Monad
main = print $ (foldr (<=<) return [f, g]) 3
where f = const Nothing
g = undefined
Questo colpisce prelude.Undefined
. Il che è strano, perché mi sarei aspettato di ridurre:
main = print $ ((const Nothing) <=< undefined <=< return) 3
main = print $ return 3 >>= undefined >>= (\_ -> Nothing)
main = print $ Nothing -- nope! instead, undefined makes this blow up
Tuttavia, lanciando l'ordine di composizione:
import Control.Monad
main = print $ (foldr (>=>) return [f, g]) 3
where f = const Nothing
g = undefined
vuol realizzare il corto circuito previsto e produce Nothing
.
main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing
Suppongo che a confronto i due approcci potrebbero avere le mele confronto stati e arance, ma si può spiegare la differenza? Ho pensato che f <=< g
fosse l'analogo monadico a f . g
, ma apparentemente non sono così simili come pensavo. Puoi spiegare perché?