【问题标题】:take IO output to another pure Haskell-function [duplicate]将 IO 输出带到另一个纯 Haskell 函数 [重复]
【发布时间】:2021-02-22 13:17:39
【问题描述】:

我是 Haskell 的新手,英语也不是我的第一语言,所以请不要因为一些拼写错误或问题表述不当而对这篇文章进行评分:对我来说,这是一场真正的斗争。

无论如何:我正在尝试生成随机坐标(Int,Int),然后在另一个 Haskell 函数中使用它。但是我在将 IO 函数结果“导出”到第二个纯类 Haskell 函数时遇到了一些问题。

这是一个我认为并希望能正确说明我的问题的例子:

genRandomPair = genRandNr

genRandNr :: IO (Int,Int)
genRandNr = do
    firstRandom <- randomRIO (1,10)
    secondRandom <- randomRIO (1,10)
    return (firstRandom,secondRandom)

如果不是很明显,那是我的问题是从 genRandNrgenRandomPair 的越界。

我会非常感谢所有友好的输入。

请注意:非常高级的代码解释对我没有帮助,因为我处于初学者水平,直到一周前从未在 Haskell 中使用过 monads 或 IO。

【问题讨论】:

  • genRandNrIO (Int, Int),但您将其键入为 IO ()。另外,genRandCoord 应该是什么?
  • 对不起@Aplet123,我编辑了那个。上面的函数主要是为了说明我希望 genRandomPair 和 genRandNr 有相同的结果。嗯,不完全一样。但我想使用 genRandomPair 中的结果。
  • 您可以再次使用do 表示法:genRandomPair = do \ pair &lt;- genRandNr \ -- do stuff with pair 其中 `` 是一个新行,因为 cmets 不能有单独的行。 question and answer threadthis excellent chapter in Learn you a Haskell 您可能会发现其他有用的东西
  • @NoNameAgent 我认为您需要在genRandomPair 中向我们提供有关您想要做什么的更多信息。按原样(在编辑之后),您的代码应该可以工作。 genRandomPair 使用 genRandNr,并具有 IO (Int, Int) 类型。您是否希望能够给genRandomPair 类型(Int, Int)?那是做不到的;如果这是您的问题,那么答案可以详细说明为什么它不能那样工作,以及为什么您不需要这样做。但目前尚不完全清楚这是否是您所要求的。
  • 不是genRandomPair = genRandNr,而是do { (x,y) &lt;- genRandNr ; z &lt;- return ( genRandomPair (x,y) ) ; .... use `z` ....}。现在你的纯函数 genRandomPair 与随机生成的 (x,y) 对一起工作,inside IO do 块。您需要调用的所有其他纯函数,以相同的方式放入do。在 Haskell 中,您不会“从 IO 中获取值以将其提供给纯函数”,而是“将纯函数放入 IO,以便它可以处理那里产生的值”。

标签: haskell io


【解决方案1】:

如果你有一个 IO (Int,Int) 值和一个函数,比如 (Int,Int),你可以使用 fmap 通过你的纯函数映射不纯的结果:

fmap myPureFunction anImpureTuple

不过,一般情况下,您可能希望 factor out the non-deterministic part 您的代码。

我知道您是 Haskell 的新手,但不幸的是,Haskell 中的随机性可能不是一个好的初学者主题。 Haskell 明确区分了纯函数和不纯动作,随机性本质上是不纯的。

要对依赖随机性的函数进行优雅的分解,需要了解 Haskell 的一些中间抽象,例如 Functor(在 fmap 的情况下)或类型类(以了解 RandomGen)。

【讨论】:

    【解决方案2】:

    Haskell 中纯函数的想法是,如果某个纯函数采用相同的参数,它总是返回相同的结果。在您的情况下,这意味着您的genRandomPair 只是一对Ints,这对不依赖于时间、日期、您的系统等。因此,您不能在没有IO 的情况下创建随机对。

    但是,您真的可以使用函数unsafePerformIO 或其他类似的函数。通常不建议这样做,但是,如果您愿意...

    【讨论】:

    • 我知道你已经用“不推荐”来限定它,但不仅应该几乎总是避免unsafePerformIO,如果你正在生成它应该真的避免随机数。通过使用unsafePerformIO,您是在说“这确实是一个纯函数,即使我无法在不使用 IO 的情况下表达它 - 编译器,您只需要相信我就可以了”。但当然,随机性从根本上说不是纯粹的。有几个关于 SO 的问题,人们使用 unsafePerformIO 正是为了这个目的,想知道为什么他们的函数总是给出相同的数字......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 2016-02-07
    • 2013-02-01
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多