Haskell:Num类型上的模式匹配 [英] Haskell: pattern matching on Num types

查看:108
本文介绍了Haskell:Num类型上的模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果没有我们将Eq指定为类型类,为什么Haskell无法对Num类型执行模式匹配?

例如:

h :: Num a => a -> a
h 0 = -1
h x = x + 1

编译此函数时,ghci抱怨:

    * Could not deduce (Eq a) arising from the literal `0'
      from the context: Num a
        bound by the type signature for:
                   h :: forall a. Num a => a -> a
        at functions.hs:9:1-20
      Possible fix:
        add (Eq a) to the context of
          the type signature for:
            h :: forall a. Num a => a -> a
    * In the pattern: 0
      In an equation for `h': h 0 = - 1
   |
10 | h 0 = -1
   |   ^

按如下所示更改函数定义即可编译并完美运行:

h :: (Num a, Eq a) => a -> a
h 0 = -1
h x = x + 1

*Main> h 0
-1
*Main>

解决方案

来自 Haskell 2010报告,标题为模式匹配的非正式语义的部分:

如果 v == k

因此,当您使用文字(例如0)作为模式时,其含义取决于==(Eq类的方法).

例如,您的函数h

h 0 = -1
h x = x + 1

可以改写为

h x | x == 0 = -1
h x          = x + 1

(隐式)使用==方法,因此需要Eq约束.

关于Haskell与许多其他语言的区别,这里有两个重要的观察结果:

  1. 并非所有类型都定义了相等性概念.除非xy的类型具有Eq实例,否则无法询问x == y.
  2. 数字类型集不是固定的.数字文字可以接受任何具有Num 实例的类型.您可以定义自己的类型并将其设置为Num的实例,并且不一定必须也具有Eq的实例.因此,并非所有数字"都可以进行相等性比较.

因此,对于函数h的上下文,不足为"a必须为数字".具体而言,上下文必须是"a必须是具有相等性检验的数字",以确保存在一种方法来检查x是否等于0以便执行模式匹配. /p>

Why can't Haskell perform pattern matching on Num types, without us specifying Eq as a type class?

For instance:

h :: Num a => a -> a
h 0 = -1
h x = x + 1

When compiling this function, ghci complains:

    * Could not deduce (Eq a) arising from the literal `0'
      from the context: Num a
        bound by the type signature for:
                   h :: forall a. Num a => a -> a
        at functions.hs:9:1-20
      Possible fix:
        add (Eq a) to the context of
          the type signature for:
            h :: forall a. Num a => a -> a
    * In the pattern: 0
      In an equation for `h': h 0 = - 1
   |
10 | h 0 = -1
   |   ^

Changing the function definition as following compiles and runs perfectly:

h :: (Num a, Eq a) => a -> a
h 0 = -1
h x = x + 1

*Main> h 0
-1
*Main>

解决方案

From the Haskell 2010 Report, the section entitled Informal Semantics of Pattern Matching:

Matching a numeric, character, or string literal pattern k against a value v succeeds if v == k

So when you use a literal (such as 0) as a pattern, its meaning depends upon == (a method of the Eq class).

For example, your function h

h 0 = -1
h x = x + 1

can be rewritten as

h x | x == 0 = -1
h x          = x + 1

You are (implicitly) using the == method, therefore you need an Eq constraint.

There are two important observations here about how Haskell differs from a lot of other languages:

  1. The notion of equality is not defined for all types. One cannot ask whether x == y unless the type of x and y has an Eq instance.
  2. The set of numeric types is not fixed. A numeric literal can take on any type that has an instance of Num. You can define your own type and make it an instance of Num, and it doesn't necessarily have to also have an instance of Eq. So not all "numbers" can be compared for equality.

So it is insufficient for the context of your function h to be "a has to be a number." The context must be, more specifically, "a has to be a number with an equality test" to ensure that there is a way to check whether x is equal to 0 in order to perform the pattern match.

这篇关于Haskell:Num类型上的模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆