【问题标题】:Correct usage of `reads` to return tuple of Int and String正确使用 `reads` 来返回 Int 和 String 的元组
【发布时间】:2014-11-23 05:41:36
【问题描述】:

我正在尝试使用 Prelude 中的 reads 函数,并使用 doctest 对其进行测试。只需加载 GHCI 并输入 reads "57x"Prelude.reads "57x" 只会产生一个空列表 [],所以我认为我必须自己导入该函数。根据文档,它应该返回一个元组。但是在运行 Doctest 和 GHCI 时,当放入除整数之外的任何字符的测试时,我会收到错误 *** Exception: Prelude.read: no parse,即 54x。如here 所述,我需要更改哪些内容才能返回正确的元组,但使用 INT 而不是 DOUBLE?

我有一个类似这样的 haskell 文件:

module StackOverflow where
import Prelude hiding (words, reads)

reads :: String -> [(Int, String)]
-- ^ Takes a string, like "57" and reads the corresponding integer value
--   out of it. It returns an empty list if there is a failure, or a list
--   containing one tuple, with the integer value as the first element of
--   the tuple and a (possibly empty) string of remaining unconvertable extra
--   characters as the second element.
--
--   Examples:
--
--   >>> reads "57"
--   [(57,"")]
--
--   >>> reads "57x"
--   [(57,"x")]
--
reads s = [(read s :: Int,"")]

【问题讨论】:

  • 你想使用内置的reads还是自己定义?
  • 鉴于预定义的 Preludes 在 GHCI 解释器中不起作用,我试图使用我自己的并覆盖 Preludes。
  • 当您尝试使用 Prelude one 时,它​​在做什么?您是否只是因为 Prelude 似乎不起作用而尝试编写新的?
  • 正确。如果我在文件module Test where import Prelude 中只有以下内容,有或没有import Prelude,输入reads "54x"Prelude.reads "54x",有或没有x,我仍然只是得到一个空列表[]。这就是为什么我自己添加了该功能,并且在我的 SO 问题 here 中提到了 words 的问题
  • 这是由于所谓的类型默认。由于reads 多态签名,您需要提供类型签名,以便它知道您期望的类型。试试reads "54x" :: [(Int, String)]。如果没有类型签名,我相信它默认为[((), String)] 类型,在这种情况下[] 将是正确的结果。

标签: haskell


【解决方案1】:

您收到“无解析”异常的原因是该类型默认为Int 以外的其他值(在本例中为())。因此,实际上,表达式reads "54x" 正在以[((), String)] 类型进行评估。这是因为为了选择合适的 Read 实例,必须在编译时完全指定类型,但这是不可能的,因为它不知道 String 应该包含什么。

您可以通过提供明确的类型签名来告诉它您期望从String 得到什么类型,就像这样

reads "54x" :: [(Int, String)]

所有表达式都可以有一个明确的类型签名,事实上,有时为了避免模棱两可的类型是必要的。

【讨论】:

    猜你喜欢
    • 2013-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    相关资源
    最近更新 更多