Ответ 1
fixIO
является эквивалентом IO
fix
.
Вероятно, вы видели это определение последовательности фибоначчи:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
который повторно использует переменную fibs
в определении fibs
для выполнения операций. Это работает, потому что мы используем лень для определения каждого элемента fibs
до его использования.
Мы можем использовать fix
, чтобы сделать то же самое без необходимости определять переменную привязывая узел для нас:
fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)
Это удобно, если вам не нужно полностью соблюдать последовательность фибоначчи, вы просто хотите знать его десятый элемент:
λ (fix $ \fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) !! 9
55
fixIO
аналогичен, за исключением того, что он позволяет вам рекурсивно выполнять выходные операции ввода-вывода. Вот почему у вас возникла ваша "заблокированная потоком" ошибка - вы использовали исходный результат без его определения.
λ fmap (take 10) . fixIO $ \fibs -> putStrLn "computing fibs" >> return (1 : 1 : zipWith (+) fibs (tail fibs))
computing fibs
[1,1,2,3,5,8,13,21,34,55]