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(实际上非常安全),您想要的函数就不可能存在。