【问题标题】:Haskell just using the read function signals an errorHaskell 仅使用 read 函数表示错误
【发布时间】:2017-03-08 09:36:54
【问题描述】:

谁能解释一下,为什么读取一个数字将其添加到另一个数字是有效的,尽管只读取一个数字是无效的?

前奏>读“5”+3 8 前奏>读“5” :33:1: 没有因使用“read”而产生 (Read a0) 的实例 类型变量“a0”不明确 可能的修复:添加修复这些类型变量的类型签名 注意:有几种可能的情况: instance Read () -- 在 `GHC.Read' 中定义 instance (Read a, Read b) => Read (a, b) -- 在 `GHC.Read' 中定义 实例(读取 a,读取 b,读取 c)=> 读取(a,b,c) -- 在 `GHC.Read' 中定义 ...加上其他 25 人 在表达式中:读“5” 在 `it' 的等式中:it = read "5"

为什么“5”有歧义?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    "5"本身没有歧义,更多的是Haskell不知道你想read是什么类型read 是一个函数定义为:

    read :: <b>Read a</b> =&gt; String -&gt; <b>a</b>

    您可以定义多种支持Read 类的类型。例如IntRead 的实例,但也是Float,您可以定义自己的类型,即Read 的实例。例如,您可以定义自己的类型:

    data WeirdNumbers = Five | Twelve
    

    然后定义一个instance Read WeirdNumbers,将"5" 映射到Five 等等。现在"5" 映射到几种类型。

    你可以简单地通过告诉 Haskell 你想读什么类型来解决这个问题。喜欢:

    Prelude> read "5" :: Int
    5
    Prelude> read "5" :: Float
    5.0
    

    顺便说一句,read "5" + 3 起作用的原因是因为在这里你提供了一个3 和一个(+) :: Num a =&gt; a -&gt; a -&gt; a。所以 Haskell 的理由是“Well 3 是一个整数,+ 要求左操作数和右操作数是同一类型,我知道我必须使用read 以便它也读取一个整数。”

    【讨论】:

    • 有趣的是,Read 的实际签名更加复杂和有趣,尽管与问题的范围无关。
    • @bereal 在 Haskell 中,类型签名几乎总是非常相关。但是read 是 IMO 的一个特别有趣的案例,因为它是我遇到的不依赖于输入类型的返回类型推断的最常见用途之一。
    • @bereal 如果read 具有类型签名String -&gt; Int,则OP 代码不会有任何问题。看来问题的症结确实在于read 在输出类型中是多态的。我不确定如何在不提及通用类型的情况下解释问题,除非仅提及快速修复“添加注释”而不解释为什么有必要。
    • @chi @Matthew 我的意思是,实际上read :: String -&gt; a 不是Read a 的方法,而是Read a 是根据readsPrec :: Int -&gt; ReadS a 等定义的。对不起,如果我没有没说清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多