Почему функция последовательности Haskell не может быть ленивой или почему рекурсивные монадические функции не могут быть ленивыми
С вопросомРаспечатка всего содержимого каталога в порядке первого порядка приводит к низкой эффективностиЯ узнал, что низкая эффективность обусловлена странным поведением рекурсивных функций монады.
Пытаться
sequence $ map return [1..]::[[Int]]
sequence $ map return [1..]::Maybe [Int]
и ghci попадет в бесконечный расчет.
Если переписать функцию последовательности в более читабельном виде, как показано ниже:
sequence' [] = return []
sequence' (m:ms) = do {x<-m; xs<-sequence' ms; return (x:xs)}
и попробовать:
sequence' $ map return [1..]::[[Int]]
sequence' $ map return [1..]::Maybe [Int]
мы получаем ту же ситуацию, бесконечный цикл.
Попробуйте ограниченный список
sequence' $ map return [1..]::Maybe [Int]
это даст ожидаемый результатJust [1,2,3,4..]
после долгого ожидания.
Из того, что мы попробовали, мы можем прийти к выводу, что хотя определение последовательности «кажется ленивым, оно строгое и должно разбирать все числа, прежде чем результат последовательности» может быть напечатан.
Не только последовательность », если мы определим функцию
iterateM:: Monad m => (a -> m a) -> a -> m [a]
iterateM f x = (f x) >>= iterateM0 f >>= return.(x:)
и попробовать
iterateM (>>=(+1)) 0
тогда происходит бесконечный расчет.
Как мы все знаем, немонадная итерация определяется так же, как и вышеупомянутый iterateM, но почему итерация ленива, а iterateM строг. Как видно из вышеизложенного, iterateM и sequence 'являются рекурсивными монадическими функциями. Есть ли что-то странное в рекурсивных монадических функциях?