2010-11-20 264 views
12

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

+8

[Haskell函数的类型:IO String-> String]的可能重复(http://stackoverflow.com/questions/1675366/a-haskell-function-of-type-io-string-string)。 – 2010-11-20 22:52:43

回答

27

作为一般规则,你写的东西是这样的:

do 
    x <- somethingThatReturnsIO 
    somethingElseThatReturnsIO $ pureFunction x 

有没有办法让“内部”出“IO诠释”,除了做在IO Monad的东西。

在单子而言,上面的代码desugars成

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

的“>> =”运算符(发音为“绑定”)不转换“IO内部”为“内部”的魔法,但它拒绝把Int直接给你。它只会将该值作为参数传递给另一个函数,并且该函数必须返回“IO”中的另一个值。默想绑定为IO单子几分钟的类型,你可以得到启发:

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

第一个参数是你最初的“IO诠释”值“comboBoxGetActive”正在恢复。第二个函数接受Int值并将其转换为其他IO值。因此你可以处理Int,但是这样做的结果永远不会从IO monad中逃脱。

(当然还有臭名昭著的“unsafePerformIO”,但在你的知识水平,你可以肯定的是,如果你使用它,那么你就错了。)

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

+1

嗨保罗,我目前正试图从System.random投入随机Ints到整数,但它不好。有没有可能帮助我?我把代码放在pastebin上一天:[link](http://pastebin.com/1s3bNztY) – 2014-09-28 08:55:16

+0

你的问题是你不能在纯粹的计算中有真正的随机数字:这就是你的类型错误的含义。所以你需要看看像RandomR这样的纯函数,它需要一个生成器并返回一个随机结果和一个新的生成器。你拿回来的发电机,并用它为你的下一个随机值。你的函数需要像randomR那样返回一个生成器。然后用顶级的getStdRandom调用你的纯函数。看看“随机”的来源,寻找一些线索。顺便说一句,你有没有考虑过如果你的随机数列表有两次相同的数字会发生什么? – 2014-09-28 10:19:31

+0

你好,保罗,没想过。你能给我一个简单的实现吗?我无法用发生器弄清楚它。 – 2014-09-28 11:06:07

11

那么,有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 -> a)大概是说

,你听说过IO在IO中发生了什么。并有非常这个很好的原因(只需阅读unsafePerformIO的文档)。所以你很可能有设计问题,但为了从经验丰富的Haskellers那里获得帮助(当然不是),你需要更详细地描述你的问题。

+3

@downvoter:你能解释一下吗?我想我的答案是正确的:我解释了你如何能够做到所要求的事情,而且这很可能是一个坏主意。 – Landei 2010-11-21 15:18:37

3

要了解这些类型用阶段 - 工序,首先查找什么也许和名单是:

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

也许一个()与(a)类似(也许Int)不同于(Int)。 类型的示例值(也许是Int)是 只是5没有

的(一个)的列表s时,可以写为([]一个)和作为(并[a])。 ([Int])的示例值是[1,7,42][]。现在

,一个(IO一个)比(一个)不同的东西,也:这是一个输入/输出-计算,其计算式(一个)的值。换句话说:它是一个脚本或程序,必须执行该脚本或程序才能生成类型值(a)。 (IO字符串)的示例为getLine,它从标准输入中读取一行文本。现在

,comboBoxGetActive的类型是:

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

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

程序的主要功能类型为(IO()),这意味着编译器和运行时系统会将您在此函数式语言中编程的方程评估为main的值,该值将被执行只要你开始程序。