2012-07-12 98 views
1

因此,我一直在享受這種具有挑戰性的語言,我目前正在爲學校做一份作業。readIO解析錯誤haskell,關閉

這就是它所說的:我需要提示用戶輸入數字列表,然後顯示列表的平均值,我非常接近找出它。不過,我得到這個奇怪的語法錯誤:

"Exception: user error (Prelude.readIO: no parse)" 

這裏是我的代碼:

module Main (listM', diginums', getList, main) where 

import System.IO  
import Data.List 

diginums' = [] 
listM' = [1, 2, 3] 
average' = (sum diginums')/(fromIntegral (length diginums')) 
getList :: IO [Double] 
getList = readLn 

main = do 
     putStrLn "Please enter a few numbers" 
     diginums' <- getList 
     putStrLn $ show average' 

終端提示:Enter a few #'s

我輸入:123

ERROR : Exception: user error (Prelude.readIO: no parse) 

我知道我的功能正在正確計算平均值。現在我認爲我的問題是,當我從用戶那裏獲取數字列表時,我沒有正確解析它們以便爲我的平均功能鍵入Double

+1

我們爲什麼要忽略縮進?您可以在這裏使縮進看起來正確,這將節省很多的痛苦。 – 2012-07-12 23:20:03

+0

大聲笑我嘗試使它正確,但每次我點擊提交答案我的瀏覽器似乎毀了正確的縮進從文本...對不起! – Shawn 2012-07-12 23:26:04

+0

雖然我們在討論縮進:確保使用空格而不是(實際)製表符。看起來不錯的佈局可能完全錯誤,因爲GHC將標籤解釋爲8個空格。 – Vitus 2012-07-13 01:41:00

回答

3

你的類型的簽名說,

getList :: IO [Double] 
getList = readLn 

讀取Double秒的列表,這意味着它預計形式

[123, 456.789, 1011.12e13] 

的輸入,但是你給它什麼可以被理解爲一個單一的數字,"123"。因此read失敗,輸入不能被解析爲[Double]

如果您想要以不同的形式解析輸入,而不是語法上正確的Haskell值(例如作爲空格分隔的數字列表),則不能使用readLn,但必須爲所需的格式編寫解析器你自己。對於數字所提到的空間分隔的列表,這是非常容易的,例如

getList :: IO [Double] 
getList = do 
    input <- getLine 
    let nums = words input 
    return $ map read nums 

如果你想在數字的形式在列表中的每個單獨一行,由一個空行結束了,你會使用累加器遞歸,

getList :: IO [Double] 
getList = completeList [] 

completeList :: [Double] -> IO [Double] 
completeList acc = do 
    line <- getLine 
    if null line 
     then return (reverse acc) 
     else completeList (read line : acc) 

解析器對於更復雜或更不剛性的格式將更難以編寫。

當解析被修復時,您會遇到您尚未習慣的問題,即值不可變。

diginums' = [] 
listM' = [1, 2, 3] 
average' = (sum diginums')/(fromIntegral (length diginums')) 

定義了三個值,則Doubleaverage'在空列表diginums'來定義的,因此它的值是

sum diginums'/fromIntegral (length diginums') = 0/0 

其是NaN

您需要的是計算Double s列表的平均值並將其應用於main中的輸入列表的函數。

average :: [Double] -> Double 
average xs = sum xs/fromIntegral (length xs) 

main = do 
    putStrLn "Please enter a few numbers" 
    numbers <- getList 
    print $ average numbers 
+0

剛剛嘗試過,沒有運氣 我輸入了:[123,456.789] #i必須加括號:S很奇怪 沒有錯誤,但結果是:NaN – Shawn 2012-07-12 23:41:54

+2

是的,對於'readLn',你需要括號,它們是語法的一部分。至於結果,由於'diginums'是一個空列表,因此您的頂級值'average'是'NaN',因爲它是'0/0'。 'main'中你綁定讀取列表的本地名稱是完全不相關的。 – 2012-07-12 23:53:36

+0

這是令人難以置信的你在haskel的知名度,我從你的解釋中學到了很多東西,謝謝你的幫助,我還有很長的路要走,但我確定我可以和你一樣好!再次感謝 ! – Shawn 2012-07-13 00:46:11

3

有Haskell中也沒有可變的變量,但它看起來像你正試圖初始化diginums'爲空列表,然後用getList填充它。

相反,也許你想要的號碼列表傳遞給average'作爲參數,是這樣的:

module Main (getList, main) where 

import System.IO 
import Data.List 


average' ds = (sum ds)/(fromIntegral (length ds)) 
getList :: IO [Double] 
getList = readLn 

main = do 
     putStrLn "Please enter a few numbers" 
     diginums' <- getList 
     putStrLn $ show $ average' diginums' 

而且,丹尼爾說,你需要輸入使用Haskell的文字列表語法,給出的方法你已經編碼了。