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

您的类型签名表明

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

其为CCD_ 12。

您需要的是一个函数,该函数计算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

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'

此外,正如Daniel所说,根据您的编码方式,您需要使用Haskell literal List语法进行输入

最新更新