Haskell 有没有安全的方法在IO中生成惰性列表?

Haskell 有没有安全的方法在IO中生成惰性列表?,haskell,lazy-evaluation,Haskell,Lazy Evaluation,我希望有一个随机数的惰性生成列表,我设法做到了,但使用了unsafeInterleaveIO: rs :: Random a => (a,a) -> IO [a] rs b = do r <- randomRIO b ns <- unsafeInterleaveIO $ rs b return (r:ns) 随机a=>(a,a)->IO[a] rs b=do r更好的方法可能是生成一个种子,然后使用随机数计算列表: randomRsIO :: Random

我希望有一个随机数的惰性生成列表,我设法做到了,但使用了
unsafeInterleaveIO

rs :: Random a => (a,a) -> IO [a]
rs b = do
  r <- randomRIO b
  ns <- unsafeInterleaveIO $ rs b
  return (r:ns)
随机a=>(a,a)->IO[a] rs b=do
r更好的方法可能是生成一个种子,然后使用
随机数计算列表:

randomRsIO :: Random a => (a, a) -> IO [a]
randomRsIO b = do
    g <- newStdGen
    return $ randomRs b g

更好的方法可能是生成一个种子,然后使用
randoms
计算列表:

randomRsIO :: Random a => (a, a) -> IO [a]
randomRsIO b = do
    g <- newStdGen
    return $ randomRs b g
如果希望“延迟生成具有效果的元素”,一种解决方案是避免传统的列表类型,并使用列表monad转换器,如管道库中的:

import System.Random
import Control.Monad
import Pipes
import qualified Pipes.Prelude as P

rs :: rs :: (Random a, MonadPlus m, MonadIO m) => (a,a) -> m a
rs b = liftIO (randomRIO b) `mplus` rs b

main :: IO ()
main = runEffect $ enumerate (rs (1::Int,10)) >-> P.take 5 >-> P.print
结果是:

*Main> :main
7
2
5
6
4
但是,这会阻止您使用传统的列表函数来使用“有效列表”;你被推入管道生态系统

(软件包中的应用程序折叠也可用于使用列表,具有和辅助功能。)

如前所述,在定义有效列表时,应尽可能使用
MonadPlus
接口。它使有效列表更不受库的影响。

如果您希望“延迟生成具有效果的元素”,一种解决方案是避免传统的列表类型,并使用列表monad转换器,如管道库中的:

import System.Random
import Control.Monad
import Pipes
import qualified Pipes.Prelude as P

rs :: rs :: (Random a, MonadPlus m, MonadIO m) => (a,a) -> m a
rs b = liftIO (randomRIO b) `mplus` rs b

main :: IO ()
main = runEffect $ enumerate (rs (1::Int,10)) >-> P.take 5 >-> P.print
结果是:

*Main> :main
7
2
5
6
4
但是,这会阻止您使用传统的列表函数来使用“有效列表”;你被推入管道生态系统

(软件包中的应用程序折叠也可用于使用列表,具有和辅助功能。)


如前所述,在定义有效列表时,应尽可能使用
MonadPlus
接口。它使有效列表更不受库的影响。

这是示例代码特有的。我正在寻找一种通用模式来惰性地构造惰性IO列表(不一定是随机列表)。
mapM
forM
sequence
foldM
,以及其他monad组合器应该可以工作。如果您可以编写一个生成1个元素的表达式,那么您可以编写一个使用这些函数生成任意数量元素的函数。(至少在大多数情况下)举个例子会有所帮助
sequence
是我第一次尝试,但没有成功。
sequence$repeat$randomRIO b
应该可以。不是在电脑上,所以我不能检查,但那应该会产生一个懒惰的无限随机数流。是的,这几乎是我天真的方法。自从
sequence
将尾部绑定到返回值后,它就不起作用了,它执行IO(这就是为什么我想到
unsafeInterleaveIO
)。尽管如此,还是非常感谢。这对于示例代码来说非常具体。我正在寻找一种通用模式来惰性地构造惰性IO列表(不一定是随机列表)。
mapM
forM
sequence
foldM
,以及其他monad组合器应该可以工作。如果您可以编写一个生成1个元素的表达式,那么您可以编写一个使用这些函数生成任意数量元素的函数。(至少在大多数情况下)举个例子会有所帮助
sequence
是我第一次尝试,但没有成功。
sequence$repeat$randomRIO b
应该可以。不是在电脑上,所以我不能检查,但那应该会产生一个懒惰的无限随机数流。是的,这几乎是我天真的方法。自从
sequence
将尾部绑定到返回值后,它就不起作用了,它执行IO(这就是为什么我想到
unsafeInterleaveIO
)。尽管如此,还是非常感谢。这通常不起作用(对于IO monad),因为值可能任意依赖于任何索引处元素的效果,对于无限列表,它包括无限索引处的元素。如果没有unsafeinterleveIO(这实际上是非常安全的),您想要的函数就不可能存在。这通常不起作用(对于IO monad),因为值可能任意依赖于任何索引中元素的效果,对于无限列表,它包括无限索引中的元素。如果没有unsafeInterleaveIO(实际上非常安全),您想要的函数就不可能存在。