haskell 输入整数数组:为什么在使用read函数时会出现解析错误?

lyr7nygr  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(99)

我一直试图在业余时间学习Haskell的基础知识,但我一直在调试这个小程序,它接受用户的整数输入,将它们转换为Int s的列表:

module Main where

------------------------------------------------------------

lines_to_words_impl :: [String] -> [String] -> [String]
lines_to_words_impl output_words input_lines =
    if null input_lines then output_words
    else lines_to_words_impl (output_words ++ (words (head input_lines))) (tail input_lines)

lines_to_words :: [String] -> [String]
lines_to_words input_lines =
    lines_to_words_impl [] input_lines

------------------------------------------------------------

words_to_ints_impl :: [Int] -> [String] -> [Int]
words_to_ints_impl output_ints input_words =
    if null input_words then output_ints
    else words_to_ints_impl (output_ints ++ (read (head input_words))) (tail input_words)

words_to_ints :: [String] -> [Int]
words_to_ints input_words =
    words_to_ints_impl [] input_words

------------------------------------------------------------

load_ints_from_input :: String -> [Int]
load_ints_from_input input =
    words_to_ints (lines_to_words (lines input))

------------------------------------------------------------

main :: IO ()
main = do
    -- Now, I just grab and try to print the first integer,
    -- which is enough to cause the read/parse error:
    user_input <- getContents
    putStrLn (show (head (load_ints_from_input user_input)))

但是当我输入一些数字时,它总是提供相同的运行时错误:
Prelude.read:没有解析
demo using godbolt
在过去的一个月里,我的业余时间一直被难倒。我唯一使用read函数的地方是在第19行,它的输入是input_wordshead,我们知道它是非空的,因为我们在if语句中的位置-它真的应该只是7,给出了godbolt链接中的示例输入。从我所知道的来看,我正确地使用了read函数(参见hoogle)来读取一个整数字符串并将其解析为Int
有人能指出为什么会发生这个解析错误吗?

k5hmc34c

k5hmc34c1#

基本原因是Haskell认为您正在解析Int s的 * 列表 *,因为您使用了:用途:

output_ints ++ (read (head input_words))

所以read (head input_words)的类型应该是[Int],你可以把它 Package 成一个单例列表:

output_ints ++ [read (head input_words)]

来解决问题
但是使用map可以更有效地完成这一点,并且可读性更强:

lines_to_words :: [String] -> [String]
lines_to_words = concatMap words

words_to_ints :: [String] -> [Int]
words_to_ints = map read

load_ints_from_input :: String -> [Int]
load_ints_from_input = words_to_ints . lines_to_words . lines

main :: IO ()
main = do
    user_input <- getContents
    print (head (load_ints_from_input user_input))

相关问题