Я учился использовать государственную монаду, и я заметил некоторое нечетное поведение с точки зрения порядка исполнения. Удаляя отвлекающие биты, которые связаны с использованием фактического состояния, скажем, у меня есть следующий код:
import Control.Monad
import Control.Monad.State
import Debug.Trace
mainAction :: State Int ()
mainAction = do
traceM "Starting the main action"
forM [0..2] (\i -> do
traceM $ "i is " ++ show i
forM [0..2] (\j -> do
traceM $ "j is " ++ show j
someSubaction i j
)
)
Запуск runState mainAction 1
в ghci выводит следующий результат:
j is 2
j is 1
j is 0
i is 2
j is 2
j is 1
j is 0
i is 1
j is 2
j is 1
j is 0
i is 0
Outside for loop
который выглядит как обратный порядок выполнения того, что можно ожидать. Я подумал, что, возможно, это причуда forM
и попробовал его с помощью sequence
, в котором, в частности, говорится, что он последовательно выполняет его вычисление слева направо так:
mainAction :: State Int ()
mainAction = do
traceM "Outside for loop"
sequence $ map handleI [0..2]
return ()
where
handleI i = do
traceM $ "i is " ++ show i
sequence $ map (handleJ i) [0..2]
handleJ i j = do
traceM $ "j is " ++ show j
someSubaction i j
Однако версия sequence
дает тот же результат. Какова фактическая логика с точки зрения порядка исполнения, который здесь происходит?