Я изучал, как использовать государственную монаду, и я заметил некоторое нечетное поведение с точки зрения порядка исполнения. Удаление отвлекающих бит, которые связаны с использованием фактического состояния, скажем, у меня есть следующий код:Порядок выполнения в монадах
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
производит тот же результат. Какова фактическая логика с точки зрения порядка исполнения, который здесь происходит?
Спасибо за подробное объяснение! Я столкнулся с этой проблемой, пытаясь перевести реализацию Java-приложения Smith-Waterman с очень мутацией. Каким будет лучший способ перевести такой код на такой язык, как Haskell? – Arbus
Вы имеете в виду «оценить» везде, где вы написали «выполнить» (как и OP). –
@Arbus Вы можете использовать 'ST'monad для выполнения мутации – jberryman