如何創建一個程序從文件中讀取一行,將其解析爲一個int並將其打印(忽略當然的例外)。有什麼像「讀」但IO字符串?Haskell - 從一個文件讀取一個int並打印它
我有這到目前爲止,但我不能圍繞IO類型得到:
readFromFile = do
inputFile <- openFile "catalogue.txt" ReadMode
isbn <- read(hGetLine inputFile)
hClose inputFile
如何創建一個程序從文件中讀取一行,將其解析爲一個int並將其打印(忽略當然的例外)。有什麼像「讀」但IO字符串?Haskell - 從一個文件讀取一個int並打印它
我有這到目前爲止,但我不能圍繞IO類型得到:
readFromFile = do
inputFile <- openFile "catalogue.txt" ReadMode
isbn <- read(hGetLine inputFile)
hClose inputFile
首先,觀察,閱讀的東西,然後立即打印出來可能會導致奇怪的錯誤:
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 String
和read
需要String
。這可以通過兩個步驟來解決:
line <- hGetLine inputFile
let isbn = readInteger line
注意兩種不同的結構<-
和let .. =
,他們做不同的事情。你能弄清楚究竟是什麼?
正如另一個答案所示,你可以做一個更簡潔的方式:
ISBN < - FMAP readInteger(hGetLine INPUTFILE)
如果你做一個簡單的事情,像read
這是偉大的。但通常需要明確命名中間結果。在這種情況下,您可以使用<-
和let .. =
構造。
可以使用readFile
功能將文件轉換爲字符串。
main = do
contents <- readFile "theFile"
let value = read $ head $ lines contents::Int
print value
您應該添加更好的錯誤檢測,或者如果沒有第一線,或者如果該值是畸形的,但是這是基本流程這一計劃將失敗....
爲什麼Int值是Int而不是IO Int? –
在Haskell的符號中,'<-'左邊的值實際上是帶有monad(在本例中爲IO)的項目類型。所以雖然'readFile'行的類型爲'IO String',但在下一行中,value只有'String'類型。 – jamshidh
所以像「value < - value」這樣的東西也會刪除IO呢? –
你可以明確指定類型,更改讀取行
isbn <- fmap read (hGetLine inputFile) :: IO Int
由於hGetLine inputFile
是IO String
類型的,你應該使用fmap
得到「內部」讀爲Int
。
不是那麼快!還有人仍然在ghc 6上! –
fmap實際上做了什麼? –
@EricMarchettiSantos它將一個簡單的函數'a - > b'作爲'IO a - > IO b'在IO下工作(它也適用於其他函子)。 – chi
這對我來說還是有點陰。 readInteger是String - > Int,因此「let .. =」將以某種方式將其更改爲IO String - > IO Integer。那是對的嗎? –
不完全。 'hGetLine inputFile'是'IO String',但是當你說'line < - hGetLine inputFile'時,'line'就是'String'。那麼'let .. ='也不會添加任何IO。你*將*必須在'do'塊的最後一行返回到IO,例如,使用'print isbn'(這會返回'IO()')。 –
在'line < - hGetLine inputFile'中,'< - '將'IO String'轉換爲'String'? –