2016-05-31 103 views
1

如何創建一個程序從文件中讀取一行,將其解析爲一個int並將其打印(忽略當然的例外)。有什麼像「讀」但IO字符串Haskell - 從一個文件讀取一個int並打印它

我有這到目前爲止,但我不能圍繞IO類型得到:

readFromFile = do 
    inputFile <- openFile "catalogue.txt" ReadMode 

    isbn <- read(hGetLine inputFile) 


    hClose inputFile 

回答

0

首先,觀察,閱讀的東西,然後立即打印出來可能會導致奇怪的錯誤:

GHCi, version 8.0.0.20160421: http://www.haskell.org/ghc/ :? for help 
Prelude λ read "123" 
*** Exception: Prelude.read: no parse 

的原因是,你沒有指定你想讀什麼類型的。您可以通過使用類型註釋解決這個:

Prelude λ read "123" :: Integer 
123 

但有時更容易引入小助手功能:

Prelude λ let readInteger = read :: String -> Integer 
Prelude λ readInteger "123" 
123 

我們的主要問題。 read(hGetLine inputFile)不起作用,因爲hGetLine inputFile返回並且IO Stringread需要String。這可以通過兩個步驟來解決:

line <- hGetLine inputFile 
let isbn = readInteger line 

注意兩種不同的結構<-let .. =,他們做不同的事情。你能弄清楚究竟是什麼?

正如另一個答案所示,你可以做一個更簡潔的方式:

ISBN < - FMAP readInteger(hGetLine INPUTFILE)

如果你做一個簡單的事情,像read這是偉大的。但通常需要明確命名中間結果。在這種情況下,您可以使用<-let .. =構造。

+0

這對我來說還是有點陰。 readInteger是String - > Int,因此「let .. =」將以某種方式將其更改爲IO String - > IO Integer。那是對的嗎? –

+0

不完全。 'hGetLine inputFile'是'IO String',但是當你說'line < - hGetLine inputFile'時,'line'就是'String'。那麼'let .. ='也不會添加任何IO。你*將*必須在'do'塊的最後一行返回到IO,例如,使用'print isbn'(這會返回'IO()')。 –

+0

在'line < - hGetLine inputFile'中,'< - '將'IO String'轉換爲'String'? –

1

可以使用readFile功能將文件轉換爲字符串。

main = do 
    contents <- readFile "theFile" 
    let value = read $ head $ lines contents::Int 
    print value 

您應該添加更好的錯誤檢測,或者如果沒有第一線,或者如果該值是畸形的,但是這是基本流程這一計劃將失敗....

+0

爲什麼Int值是Int而不是IO Int? –

+1

在Haskell的符號中,'<-'左邊的值實際上是帶有monad(在本例中爲IO)的項目類型。所以雖然'readFile'行的類型爲'IO String',但在下一行中,value只有'String'類型。 – jamshidh

+0

所以像「value < - value」這樣的東西也會刪除IO呢? –

2

你可以明確指定類型,更改讀取行

isbn <- fmap read (hGetLine inputFile) :: IO Int 

由於hGetLine inputFileIO String類型的,你應該使用fmap得到「內部」讀爲Int

+0

不是那麼快!還有人仍然在ghc 6上! –

+0

fmap實際上做了什麼? –

+0

@EricMarchettiSantos它將一個簡單的函數'a - > b'作爲'IO a - > IO b'在IO下工作(它也適用於其他函子)。 – chi

相關問題