2012-07-13 58 views
13

我有以下功能:如何從IO動作正常值在Haskell

get :: Chars -> IO Chars 
get cs = do 
    char <- getChar 
    let (dats, idx) = (curData cs, curIndex cs) 
    let (x,y:xs) = splitAt idx dats 
    let replacement = x ++ (ord char) : xs 
    return $ Chars replacement idx 

,我想獲得一個Chars出來,一個IO動作。我有沒有想法如何做到這一點,或者如果它甚至是可能的。

Chars基本上只是一個容器,名爲curData的[Int]和名爲curIndex的Int。細節並不重要,我只想知道是否有這種功能返回Chars而不是IO Chars的方法。

如果不是,我該如何將此作爲參數傳遞給需要Chars的函數?我對Haskell IO很陌生,但我不認爲我需要所有以Chars作爲參數的函數,而不得不以IO Chars作爲參數,然後提取並重新打包它們。這似乎沒有必要。

謝謝!

+5

難道我們沒有一個規範的「我如何獲得一個'了'出'IO了'的?「這個問題是重複的嗎? – 2012-07-13 12:08:53

+8

這裏有太多內容豐富的答案,沒有足夠的可愛的貓咪圖片,所以我只想在這裏留下這個:http://spl.smugmug.com/Humor/Lambdacats/ trapd-in-IO-monad-plz-help/960526421_MnNqB-S-1.jpg – rtperson 2012-07-13 13:22:07

回答

18

你不能,因爲這會違反referential transparency

通過這種方式,Haskell中的IO完全可以區分其結果和效果可能會因環境/用戶與純函數的交互而​​變化的操作,當您使用相同的輸入參數調用它們時,結果不會改變。

爲了將結果傳遞給輸入爲Chars的純函數,您必須將您的IO操作調用到另一個IO操作中,將結果與<-運算符綁定到一個變量並將其傳遞給您的純函數。僞例如:

myPureFunction :: Chars -> ... 

otherAction :: Chars -> IO() 
otherAction cs = do 
    myChars <- get cs 
    let pureResult = myPureFunction myChars 
    ... 

如果您在Haskell是新的IO,你不妨在Learn You a Haskell for a Great Good!Real World Haskell看看輸入和輸出章節。

實際上有一種方法可以簡單地從IO操作中獲得純價值,但在您的情況下,您不應該這樣做,因爲您正在與環境進行交互:不安全的方式只有在您可以保證你不違反參考透明度。

+0

我添加了關於IO的書籍章節的參考文獻 – 2012-07-13 10:07:22

+0

謝謝!我認爲這有意義了,我讀過LYAH的所有內容,但它是我已經做了一段時間,所以我不知道如何處理這個問題。 所以,我有幾個函數,需要一個'Chars'並返回一個'Chars'但不要觸及IO 。我是否應該修改那些僅僅爲了簡單而返回'IO Chars'?我不願意改變這種情況,但是理論上這個程序在這種情況下仍然可以工作。 – 2012-07-13 16:19:02

+1

不,你不應該給提供類型保證的參考透明度當你可以的時候。所以讓這些函數成爲,不要讓它們返回類似'IO a'的東西。 – 2012-07-13 16:50:27

8

這是不可能的(我說謊,有一種非常不安全的方式來欺騙你的出路)。

問題是,如果執行任何I/O,程序的行爲和結果可能不僅僅取決於所使用函數的顯式參數,因此必須通過使用IO something來聲明該類型。

您在main結合的結果(或東西從main調用),然後再進行精功能,在let結合的結果使用純函數的IO a作用的結果,

cs ::Chars 
cs = undefined 

main = do 
    chars <- get cs 
    let result = pureFunction chars 
    print result 

或者,如果你想申請chars的功能型Chars -> IO b

main = do 
    chars <- get cs 
    doSomething chars 
+0

只是一個非常小的提示:在你的例子中,他的'get'函數應該採用'Chars'。 – 2012-07-13 09:00:45

+0

謝謝,錯過了。 – 2012-07-13 09:04:03

+0

不客氣;) – 2012-07-13 09:05:50