1

所以我一直很享受这种具有挑战性的语言,我目前正在为学校做作业。

这就是它所说的:我需要提示用户输入数字列表,然后显示列表的平均值,我非常接近弄清楚。但是我得到了这个奇怪的解析错误:

"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我的平均功能。

4

2 回答 2

3

你的类型签名说

getList :: IO [Double]
getList = readLn

读取Doubles 的列表,这意味着它需要表单的输入

[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

您需要的是一个计算Doubles 列表平均值的函数,并将其应用于main.

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

main = do
    putStrLn "Please enter a few numbers" 
    numbers <- getList
    print $ average numbers
于 2012-07-12T23:35:42.680 回答
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 文字列表语法进行输入,因为您已经编码了它。

于 2012-07-13T00:02:35.563 回答