2013-10-26 83 views
0

好吧,讓我們假設我有一個函數,它接受一個字符串並返回由文本文件指定的字符串的某個值。文本文件將如下所示。另一個haskell IO問題

你好 - 2
再見 - 3

因此函數將返回2給出 「你好」 和3所給出的 「再見」。現在,功能型重量(我不能改變它,因爲這是該框架的一部分):

type Weight = String -> Int 

如何實現這樣的功能,因爲它必須是類型重量。問題是,我不知道如何讓體重知道給定一個字符串返回什麼值。我無法對這些值進行硬編碼,因爲它們在不同的文本文件中會有所不同。我不能在函數內部讀取文件或類似的東西,對吧?還有其他選擇嗎?

回答

3

你有兩個選擇,

assignWeight :: String -> IO Int 
assignWeight = do 
    file <- readFile whatever 

    -- parse file and extract a function assigning strings to their weights 
    return $ parseFile file 

或者,

assignWeight :: String -> Weight 
assignWeight file = parseFileAndExtractWeights file 

然後閱讀main和使用鑽營的文件。因此,有沒有頂級的功能,但我們仍然後來得到我們的功能通過部分申請assignWeight到文件

main = do 
    weights <- assignWeight `fmap` readFile whatever 
    -- use weights 

的內容,但你不能在Weight類型的計算進行IO,所以你要麼必須在其他地方執行,並將類型傳遞給它或者只是改變類型。沒有別的辦法。

+0

'READFILE無論>> =回報。 assignWeight'可以寫爲'assignWeight <$> readFile whatever'。 – kqr

+0

謝謝,這就是我的想法。不幸的是,這些都不令人滿意,所以我不得不尋找一些解決方法。我只是想,也許你可以模擬一個全局固定變量來保存文件的內容,因爲在文件內容被讀取後它不會改變。但我看不到這樣做的方式。 – redFur

+0

@ user2922609你不能。 Haskell不允許這種突變 – jozefg

0

全球不能有assignWeight,但您可以在本地使用您想要的真正的非IO類型。我認爲下面的方法是用於分離一元代碼和非一元代碼的常見模式。

import Data.Maybe 
import Control.Applicative 

parseFile :: IO [(String, Int)] 
parseFile = read <$> readFile "Parse.txt" 

main = do 
     content <- parseFile 
     let assignWeight x = fromJust $ lookup x content 
     print $ process assignWeight 

type Weight = String -> Int 

process :: Weight -> Int 
process x = 0 

這裏assignWeight是正確的類型。你可以傳遞它:看看我是如何將它傳遞給非一元的process函數的。正如其他評論者所指出的那樣,您不能在頂級定義assignWeight,但在本地擁有並傳遞是一種常用的方法。

這裏是一個更模塊化的方法:

getAssignWeight :: IO Weight 
getAssignWeight = do 
     content <- parseFile 
     let assignWeight x = fromJust $ lookup x content 
     return assignWeight 

main = do 
     assignWeight <- getAssignWeight 
     print $ process assignWeight