2010-11-20 155 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的值,該值將被執行只要你開始程序。