Haskell从文件读取整数到列表

时间:2017-04-14 19:01:44

标签: haskell io

我有一行简单的文本文件:

6 195 265 750 265 750 196

我有一个功能:

executeList :: Integer -> [Integer] -> [String]
executeList n x = [reverseAndAdd n i | i <- x]

它接受一个整数,整数列表并返回一个字符串数组。

我想要做的是将该文本文件读取到[Integer]列表并将其传递给executeList函数。 这是我的代码:

main = do  
    let list = []
    handle <- openFile "data.txt" ReadMode
    contents <- hGetContents handle
    let singlewords = words contents
        list = f singlewords
    print list
    hClose handle   
f :: [String] -> [Integer]
f = map read

我在这里找到了: Haskell file reading

当我运行'main'时,我得到了这个输出: [6,195,265,750,265,750,196]

但是当我尝试将它传递给executeList:

let list = main
executeList 0 list

我收到此错误:

<interactive>:103:15: error:
* Couldn't match expected type `[Integer]' with actual type `IO ()'
* In the second argument of `executeList', namely `list'
  In the expression: executeList 0 list
  In an equation for `it': it = executeList 0 list

如果我检查该列表的类型,我会得到:

list :: IO()

我在互联网上查找了如何将IO()转换为[Integer],但没有发现任何有用的东西。也许有人可以告诉我进行转换的方法?

1 个答案:

答案 0 :(得分:1)

简短的回答是,您无法将IO()转换为[Integer]

好像你误解了IO monad。大多数函数返回一个值。返回类型为IO a的函数返回一个I / O操作,该操作在返回类型a的值之前执行某种排序I / O.在您的情况下,IO ()是一个I / O操作,它将返回(),这只是一个空元组。当您编写这样的控制台程序来读入数据然后打印出一些结果时,您通常会遵循以下模式:

  1. 从文件或命令行读取输入
  2. 将数据传递给计算功能
  3. 打印结果
  4. 你的整个程序最终将生活在IO monad中。 do是一个符号,它是绑定运算符>>=的语法糖。该运算符允许我们将monadic计算链接在一起。代码中的<-从monad中提取值(在您的情况下是IO操作)并将其存储在变量中。让我们看一下hGetContents的类型签名。从GHCI我们可以知道这个函数的类型为hGetContents :: Handle -> IO String它需要Handle并返回一个返回字符串的I / O操作。当您调用contents <- hGetContents handle时,程序使用您指定的文件句柄调用hGetContents,然后从返回的IO操作中提取字符串,并将该字符串存储在变量内容中。所以现在你已经阅读了输入。在将数字转换为实际整数类型之后,下一步是调用您的函数,即简单调用let data = executeList 0 list从那里您可以使用print data输出数据。重要的是要记住你在IO monad中的整个时间。最后,您的整个主要功能应如下所示:

    main = do
        handle <- openFile "data.txt" ReadMode
    contents <- hGetContents handle
    let singlewords = words contents
        list = f singlewords
        data = executeList 0 list
    print data
    hClose handle   
    
    f :: [String] -> [Integer]
    f = map read