Я озадачен. Я могу написать это:
import Control.Monad
main = print $ head $ (foldr (.) id [f, g]) [3]
where f = (1:)
g = undefined
и выход 1
. Это имеет смысл, потому что это сводится к:
main = print $ head $ ((1:) . undefined . id) [3]
main = print $ head $ (1:) ((undefined . id) [3])
main = print $ head $ 1 : ((undefined . id) [3])
main = print $ 1
Но если я использую смутно похожую монадическую технику, она не работает так же:
import Control.Monad
main = print $ (foldr (<=<) return [f, g]) 3
where f = const Nothing
g = undefined
Это попадает в prelude.Undefined
. Что странно, потому что я ожидал бы, что он уменьшится:
main = print $ ((const Nothing) <=< undefined <=< return) 3
main = print $ return 3 >>= undefined >>= (\_ -> Nothing)
main = print $ Nothing -- nope! instead, undefined makes this blow up
Однако, изменив порядок композиции:
import Control.Monad
main = print $ (foldr (>=>) return [f, g]) 3
where f = const Nothing
g = undefined
выполняет ожидаемое короткое замыкание и выдает Nothing
.
main = print $ (const Nothing >=> undefined >=> return) 3
main = print $ (const Nothing 3) >>= undefined >>= return
main = print $ Nothing >>= undefined >>= return
main = print $ Nothing
Я полагаю, что сравнение двух подходов могло бы сравнить яблоки и апельсины, но можете ли вы объяснить разницу? Я думал, что f <=< g
был монадическим аналогом f . g
, но они, по-видимому, не так аналогичны, как я думал. Можете ли вы объяснить, почему?