У меня есть функция f :: [a] -> b
, которая работает с бесконечными списками (например, take 5
, takeWhile (< 100) . scanl (+) 0
и т. Д.). Я хочу передать эту функцию значениям, генерируемым строгими монадическими действиями (например, randomIO
).Работа бесконечных списков со строгими монадами
С this question, я узнал, что трюк подход repeat
и sequence
не работает для жестких монад, как пример ниже шоу:
import Control.Monad.Identity
take 5 <$> sequence (repeat $ return 1) :: Identity [Int]
-- returns `Identity [1,1,1,1,1]`
-- works because Identity is non-strict
take 5 <$> sequence (repeat $ return 1) :: IO [Int]
-- returns `*** Exception: stack overflow`
-- does not work because IO is strict
Таким образом, вместо этого, я думал об использовании функции «внутри «монадический контекст. Я был вдохновлен этой circular programming example и попробовал:
let loop = do
x <- return 1
(_, xs) <- loop
return (take 5 xs, x:xs)
in fst loop :: Identity [Int]
-- Overflows the stack
и
import Control.Monad.Fix
fst <$> mfix (\(_, xs) -> do
x <- return 1
return (take 5 xs, x:xs)) :: Identity [Int]
-- Overflows the stack
и даже
{-# LANGUAGE RecursiveDo #-}
import System.Random
loop' = mdo
(xs', xs) <- loop xs
return xs'
where loop xs = do
x <- randomIO
return (take 5 xs, x:xs)
print $ loop'
-- Returns a list of 5 identical values
Но ни одна из этих работ. Я также попытался Conduit
подход, который не работал ни даже в Identity
случае:
import Conduit
runConduitPure $ yieldMany [1..] .| sinkList >>= return . take 5
Поэтому я хотел бы знать:
Почему никто из «круговой» не подходит выше работы?
Если существует решение, которое не включает
unsafeInterleaveIO
. (возможноiteratee
s,Arrow
ы?)
В общем, это сложная проблема. Для случайных чисел, в частности, есть простой выход: 'randoms <$> newStdGen :: Random a => IO [a]' - это бесконечный случайный список того, что вы хотите (это «Random»). – Alec
@Alec Спасибо за комментарий. Я использую 'randomIO' здесь только для простоты примеров. На практике я хотел бы обрабатывать сообщения, полученные через сокеты. –
Так что-то вроде бесконечного списка сообщений, полученных от сокета? – Alec