2017-04-14 32 views
0

我有一行簡單的文本文件:從文件哈斯克爾讀整數到列表

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

當我運行 '主' 我得到這樣的輸出: [6,195,265,750,265,750,196]

但是當我嘗試將它傳遞像這樣執行清單:

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()爲[整數]上,但發現沒有什麼用處。也許有人可以告訴我做這種轉換的方式嗎?

+1

而不是'print list',在你的main中使用'print(executeList 0 list)'?請注意,沒有(安全)功能'IO a - > a'。 – Zeta

+0

謝謝!還有一個問題。是否有可能將此列表寫入同一函數中的某個其他文件?我嘗試添加如下內容: outh < - openFile「results.txt」WriteMode hPrint outh(executeList 0 list) hClose outh – motleycrue

+0

但get:解析錯誤輸入'< - '。也許這個狀態應該是一個'做'塊? 錯誤。 – motleycrue

回答

0

簡短的回答是,您不能將IO()轉換爲[Integer]

看起來好像你誤解了IO monad。大多數函數返回一個值。返回類型爲IO a的函數在返回類型爲a的值之前返回執行某種排序I/O的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