如何使用“do notation”读取和处理文件?

时间:2014-10-16 13:23:15

标签: haskell

例如,我想读取一个只包含整数的文件,并在函数中对这些整数执行某些操作:

getIntFromFile :: () -> Int
getIntFromFile _ = do
                     h <- openFile "/tmp/file" ReadMode
                     str <- hGetLine h
                     let x = read str :: Int

                     str <- hGetLine h
                     let y = read str :: Int

                     hClose h
                     x + y

当我将包含此函数的文件加载到ghci时,我得到了输出

Prelude System.IO> :l graphBat.hs
[1 of 1] Compiling Plugins.GraphBat ( graphBat.hs, interpreted )

graphBat.hs:77:22:
    Couldn't match type ‘IO b0’ with ‘() -> Int’
    Expected type: IO Handle -> (Handle -> IO b0) -> () -> Int
      Actual type: IO Handle -> (Handle -> IO b0) -> IO b0
    In a stmt of a 'do' block: h <- openFile "/tmp/file" ReadMode
    In the expression:
      do { h <- openFile "/tmp/file" ReadMode;
           str <- hGetLine h;
           let x = ...;
           str <- hGetLine h;
           .... }
    In an equation for ‘getIntFromFile’:
        getIntFromFile
          = do { h <- openFile "/tmp/file" ReadMode;
                 str <- hGetLine h;
                 let x = ...;
                 .... }

graphBat.hs:85:22:
    Couldn't match expected type ‘IO b0’ with actual type ‘Int’
    In the first argument of ‘(+)’, namely ‘x’
    In a stmt of a 'do' block: x + y

graphBat.hs:85:26:
    Couldn't match expected type ‘IO b0’ with actual type ‘Int’
    In the second argument of ‘(+)’, namely ‘y’
    In a stmt of a 'do' block: x + y
Failed, modules loaded: none.

我做错了什么?我应该如何编写一个读取文件的典型函数,处理该文件并返回此处理的结果?

1 个答案:

答案 0 :(得分:6)

如果你做IO,你必须在IO monad中工作:

getIntFromFile :: () -> IO Int   -- Added IO here
getIntFromFile _ = do
                     h <- openFile "/tmp/file" ReadMode
                     str <- hGetLine h
                     let x = read str :: Int

                     str <- hGetLine h
                     let y = read str :: Int

                     hClose h
                     return (x + y)   -- Added return

您也可以删除()参数并以:

开头
getIntFromFile :: IO Int   -- Added IO here
getIntFromFile = do
             ...

事实上,使用() -> ...是Haskell中的反模式。