从 randomIO 列表中打印 x randomIO 值

发布于 2024-12-11 07:18:23 字数 527 浏览 0 评论 0 原文

我已经得到了这段代码,我应该解释它的非终止性并提出可能的修复方案。

randomW =  do randomvalues <- sequence (repeat (randomIO :: IO Float))
              print (take 10 randomvalues)

修复的条件是继续生成无限列表,以便我们可以使用 take 函数。

我认为问题源于序列函数的不那么懒惰的本质,它试图到达由 repeat (randomIO :: IO Float) 生成的列表的末尾,从而导致非终止。

我也不确定 randomIO 上是否可以使用重复功能。

test = do random <- repeat (randomIO :: IO Float)
          print random

这会产生类型错误。 Print 似乎无法处理 IO Float,这似乎表明您可以在 IO Float 类型上使用重复。

I have been given this snippet of code and am supposed to explain it's non termination and propose a possible fix.

randomW =  do randomvalues <- sequence (repeat (randomIO :: IO Float))
              print (take 10 randomvalues)

Condition for the fix is to keep generating an infinite list so we may use the take function.

I think the problem stems from the not-so-lazy nature of the sequence function, which tries to reach the end of the list generated by repeat (randomIO :: IO Float), leading to non termination.

I'm also not sure about whether the repeat function is possible on randomIO.

test = do random <- repeat (randomIO :: IO Float)
          print random

Which yields a type error. Print can't seem to be able to handle an IO Float, which seems to suggest that you can use repeat on type IO Float.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嗳卜坏 2024-12-18 07:18:23

所以:

repeat :: a -> [a]
randomIO :: Random a => IO a
sequence :: Monad m => [m a] -> m [a]

=>

repeat (randomIO :: IO Float) :: [IO Float]

因此,当您这样做时:

random <- repeat (randomIO :: IO Float)

您实际上是在利用此处的列表 monad,因此 random 的类型为 IO Float。由于您位于列表 monad 中,因此最后一条语句需要具有类型 [a],但它具有类型 IO (),因为它是对 print 的调用,因此出现类型错误。

序列的全部要点是将这个 [IO a] 转换为 IO [a],您可以执行该操作来获取随机值列表,并希望打印该列表。现在,当您执行这样的 IO 时,需要一次性执行所有操作,除非使用 unsafeInterleaveIO,在这种情况下不建议这样做。所以它尝试获取无限列表...并挂起(它可能在某个时候堆栈溢出,我不确定)。

要获得无限的随机值列表,您不需要所有这些,只需获取随机种子,并纯粹从种子计算随机值即可。

您应该能够使用这些 函数

randomIO :: Random a => IO a        -- to provide an IO Int
mkStdGen :: Int -> StdGen           -- to obtain a random generator from that Int
randoms :: RandomGen g => g -> [a]  -- to generate the infinite list

请注意,最后两个函数是纯函数。阅读此帖子可能会给您更多想法。


编辑:

如何使用 mkStdGen 的示例:

randomList :: Random a => IO [a]
randomList = do seed <- randomIO
                let gen = mkStdGen seed
                return (randoms gen)

我现在无法测试它,但这应该可行。不过,您可能希望使其适应您的用例。

对于您的其他问题:

map :: (a -> b) -> [a] -> [b]
print :: Show a => a -> IO ()

=>
地图打印:: 显示 => [一]-> [IO()]

这可能不是你想要的,对吧?
如果你只是想打印一个列表,不需要mapprint可以处理列表。

So:

repeat :: a -> [a]
randomIO :: Random a => IO a
sequence :: Monad m => [m a] -> m [a]

=>

repeat (randomIO :: IO Float) :: [IO Float]

So when you do:

random <- repeat (randomIO :: IO Float)

You're actually exploiting the list monad here, so random has type IO Float. Since you're in the list monad, your last statement needs to have type [a], but it has type IO () since it's a call to print, hence the type error.

The whole point of sequence is to transform this [IO a] into an IO [a] that you can perform to obtain a list of random values, and hopefully print this list. Now, when you perform an IO like this, it needs to be performed all at once, unless using unsafeInterleaveIO, which is not recommended in this case. So it tries to get that infinite list... and hangs (it might stack overflow at some point, I'm not sure).

To get an infinite list of random values, you don't need all this, just to obtain a random seed, and compute random values purely from the seed.

You should be able to construct an infinite list of random values using these functions:

randomIO :: Random a => IO a        -- to provide an IO Int
mkStdGen :: Int -> StdGen           -- to obtain a random generator from that Int
randoms :: RandomGen g => g -> [a]  -- to generate the infinite list

Notice that the last two functions are pure. Reading this thread might give you some more ideas.


EDIT:

Example of how you should use mkStdGen:

randomList :: Random a => IO [a]
randomList = do seed <- randomIO
                let gen = mkStdGen seed
                return (randoms gen)

I can't test it right now but this should work. You probably want to adapt this to your use case though.

For your other question:

map :: (a -> b) -> [a] -> [b]
print :: Show a => a -> IO ()

=>
map print :: Show a => [a] -> [IO ()]

This probably isn't what you want, right?
If you just want to print a list, no need for map, print can handle lists.

枫林﹌晚霞¤ 2024-12-18 07:18:23

您的第一个代码不起作用的原因是您试图对无限数量的 IO 操作进行排序。由于这使用了严格的 IO,因此在执行所有操作之前不允许程序继续,这将永远持续下去。

一个简单的解决方案是在对它们进行排序之前采取您需要的操作数量,例如:

 randomW = do values <- sequence (take 10 $ repeat (randomIO :: IO Float))
              print values

可以使用replicateM从< code>Control.Monad:

 randomW = do values <- replicateM 10 (randomIO :: IO Float)
              print values

或者,您可以使用randoms基于单个随机种子创建无限的随机数列表(类似于Ptival的答案):

 randomW = do gen <- newStdGen
              let randomValues = randoms gen :: [Float]
              print (take 10 randomValues)

在这里,我们只使用单个 IO 操作并且无限列表是基于此延迟生成的,因此没有无限数量的副作用可以运行。

The reason why your first code does not work, is that you're trying to sequence an infinite number of IO actions. Since this uses strict IO, the program is not allowed to continue before all the actions have been performed, which will take forever.

A simple solution is to take the number of actions you need before sequencing them, for example:

 randomW = do values <- sequence (take 10 $ repeat (randomIO :: IO Float))
              print values

This can be written more succinctly using replicateM from Control.Monad:

 randomW = do values <- replicateM 10 (randomIO :: IO Float)
              print values

Or, you can use randoms to make an infinite list of random numbers based on a single random seed (similar to Ptival's answer):

 randomW = do gen <- newStdGen
              let randomValues = randoms gen :: [Float]
              print (take 10 randomValues)

Here, we only use a single IO action and the infinite list is generated lazily based on that, so there is no infinite number of side effects to run.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文