無限リスト(例えば、take 5
、など)で動作する関数f :: [a] -> b
があります。厳密なモナドアクション(たとえば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
しかし、これらの作品のどれを。私もどちらかでもIdentity
の場合には動作しませんでしたConduit
アプローチを試してみました:
import Conduit
runConduitPure $ yieldMany [1..] .| sinkList >>= return . take 5
したがって、私は知っているしたいと思います:
「円形」のどれもが仕事の上に接近しないのはなぜ?
これには、
unsafeInterleaveIO
を含まない解決策が存在する場合。 (多分iteratee
秒、Arrow
秒?)
一般的に、これは厳しい問題です。特に乱数の場合、簡単な方法があります: 'randoms <$> newStdGen :: Random a => IO [a]'はあなたが望むもの(無作為)の無限ランダムリストです。 – Alec
@Alecコメントをいただきありがとうございます。ここでは例を簡単にするために 'randomIO'を使用しています。実際には、ソケット経由で受信したメッセージを処理したいと思います。 –
ソケットから受信したメッセージの無限リストのようなものですか? – Alec