所以我一直很喜欢这种富有挑战性的语言,我目前正在为学校做作业。
它是这样说的:我需要提示用户输入一个数字列表,然后显示列表的平均值,我很快就要弄清楚了。然而,我得到了这个奇怪的解析错误:
"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'))
定义了三个值,Double
值average'
是根据空列表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语法进行输入