【问题标题】:Converting IO Int to Int将 IO Int 转换为 Int
【发布时间】:2011-05-13 05:31:23
【问题描述】:

我创建了一个组合框,将xmlWidget 转换为comboBox,函数castTocomboBox 现在我想获取活动项目的文本或索引。问题是,如果我使用comboBoxGetActive 函数,它会返回IO Int 结果,我需要知道如何获得Int 值。我试图阅读有关 monad 的内容,以便了解在这种情况下可以做什么,但我似乎不明白。我很感激我能得到的所有帮助。我应该提到我使用Gladegtk2hs

【问题讨论】:

标签: haskell syntax io monads


【解决方案1】:

作为一般规则,你可以这样写:

do
   x <- somethingThatReturnsIO
   somethingElseThatReturnsIO $ pureFunction x

没有办法从“IO Int”中取出“Int”,除非在 IO Monad 中做其他事情。

在 monad 术语中,上面的代码脱糖成

somethingThatReturnsIO >>= (\x -> somethingElseThatReturnsIO $ pureFunction x)

“>>=”运算符(发音为“bind”)具有将“IO Int”转换为“Int”的魔力,但它拒绝直接将 Int 提供给您。它只会将该值作为参数传递给另一个函数,并且该函数必须在“IO”中返回另一个值。思考一下 IO monad 的绑定类型几分钟,你可能会有所启发:

>>= :: IO a -> (a -> IO b) -> IO b

第一个参数是“comboBoxGetActive”返回的初始“IO Int”值。第二个是获取 Int 值并将其转换为其他 IO 值的函数。因此,您可以处理 Int,但这样做的结果永远不会从 IO monad 中逃脱。

(当然有臭名昭著的“unsafePerformIO”,但以您的知识水平,您可能会确定如果您使用它,那么您做错了。)

(实际上脱糖相当复杂,以允许失败的模式匹配。但你可以假装我写的是真的)

【讨论】:

  • 嗨,保罗,我目前正在尝试将随机整数从 System.random 转换为整数,但它并不顺利。有没有可能你可以帮助我?我在pastebin上放了一天的代码:link
  • 您的问题是在纯计算中不能有真正的随机数:这就是您的类型错误的意思。所以你需要看看像randomR这样的纯函数,它接受一个生成器并返回一个随机结果和一个新的生成器。您获取返回的生成器并将其用作下一个随机值。您的函数需要像 randomR 一样获取并返回一个生成器。然后在顶层使用 getStdRandom 调用您的纯函数。查看“随机数”的来源以获取一些线索。顺便说一句,你有没有考虑过如果你的随机数列表有两次相同的数字会发生什么?
  • 嗨,保罗,还没有想过。你能给我一个简单的实现吗?我无法用生成器弄清楚。
  • 你的类型签名应该是“makeIntSet:: Int -> [Int] -> StdGen -> (Set Int, StdGen)”。将此与 GetStdRandom 的第一个参数的类型进行比较
【解决方案2】:

嗯,还有 unsafePerformIO:http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/System-IO-Unsafe.html#v:unsafePerformIO

(如果你想知道如何找到这个方法:去http://www.haskell.org/hoogle搜索你需要的签名,这里IO a -&gt; a

也就是说,您可能听说过“IO 中发生的事情留在 IO 中”。这有 非常 充分的理由(只需阅读 unsafePerformIO 的文档)。所以你很可能有设计问题,但是为了从有经验的 Haskeller 那里获得帮助(我当然不是),你需要更详细地描述你的问题。

【讨论】:

  • @downvoter:你能解释一下吗?我认为我的回答是正确的:我解释了你可以如何做被问到的事情,这很可能是个坏主意。
【解决方案3】:

要逐步了解这些类型是什么,首先查看 Maybe 和 List 是什么:

data Maybe a = Nothing | Just a
data [a]     = [] | a : [a]

(Maybe a) 是与 (a) 不同的类型,就像 (Maybe Int) 不同于 (Int)。 (Maybe Int) 类型的示例值为 只有 5 个没有

(a) 的列表可以写成 ([ ] a) 和 ([a])。 ([Int]) 的示例值为 [1,7,42][ ]

现在,(IO a) 也与 (a) 不同:它是一个输入/输出计算,计算类型为 ( 一个)。换句话说:它是一个脚本或程序,必须执行它才能生成一个类型为 (a) 的值。 (IO String) 的一个例子是 getLine,它从标准输入中读取一行文本。

现在,comboBoxGetActive 的类型是:

comboBoxGetActive :: ComboBoxClass self => self -> IO Int

这意味着,comboBoxGetActive 是一个函数 (->),它映射自具有类型类 ComboBoxClass 实例的任何类型(原始类型类在某种程度上类似于 java 接口)到 (IO Int)。每次,这个函数 (->) 使用相同类型的输入值 (self) 进行评估(无论该类型是什么),它会产生相同的值:它始终是相同的类型值 (IO Int),这意味着它始终是同一个脚本。但是,当您在不同时间执行同一个脚本时,它可能会产生不同的类型值 (Int)。

你的程序的main函数有类型(IO()),这意味着编译器和运行时系统评估你用这个函数语言编写的方程到main的值,这将在您启动程序后立即执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-03
    • 2012-01-07
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 1970-01-01
    相关资源
    最近更新 更多