2016-05-31 106 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

相关问题