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

Input array of integers: Why is there a parse error when using the read function?

提问人:Elliott 提问时间:10/9/2023 更新时间:10/9/2023 访问量:79

问:

我一直在尝试在业余时间学习 Haskell 的基础知识,但我一直坚持调试这个小程序,它从用户那里获取整数输入,将它们转换为 s 列表:Int

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:无解析

使用 Godbolt 的演示

在过去的一个月里,在我的业余时间里,我一直被难住了。我唯一使用该函数的地方是第 19 行,它的输入是 of ,我们知道它是非空的,因为我们在 if 语句中的位置 - 它真的应该只是在 godbolt 链接中给出示例输入。据我所知,我正确地使用了 read 函数(参见 hoogle)来读取整数字符串并将其解析为 .readheadinput_words7Int

有人可以指出为什么会发生此解析错误吗?

解析 Haskell IO

评论

1赞 Daniel Wagner 10/9/2023
words已经在换行符边界处中断了单词,所以你可以用它来代替和扔掉。lineslines_to_words{,_impl}

答:

4赞 willeM_ Van Onsem 10/9/2023 #1

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

output_ints ++ (read (head input_words))

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

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))

评论

3赞 lsmor 10/10/2023
@Elliott通知,不等同于 。实际上,后者永远不会编译,但前者会这样做,如果是一个字符串列表,每个字符串代表一个整数列表。不要那么相信 chatGPT ;)output_ints ++ (read (head input_words))(output_ints ++ read) (head input_words)input_words
1赞 willeM_ Van Onsem 10/10/2023
@Elliott:聊天机器人肯定有附加值,但需要小心:它实际上只是根据以前的单词和某个“上下文”来预测单词的东西。因此,这些机器人倾向于“幻觉”:仅仅因为一个句子经常出现在某个上下文中,它们就包含了该句子。即使上下文不同。
1赞 Cubic 10/10/2023
@Elliott虽然像 ChatGPT 这样的工具有时可以作为一种学习辅助工具,但它们经常是错误的。在这种情况下,你从 ChatGPT 那里得到的声明只是纯粹的胡说八道,恰好听起来足够合理,令人信服。使用此类工具时要非常小心。