Haskell:Num类型的模式匹配

时间:2018-02-11 05:51:37

标签: haskell pattern-matching

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

例如:

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>

1 个答案:

答案 0 :(得分:4)

Haskell 2010 Report开始,名为模式匹配的非正式语义的部分:

  

如果 v == ,则将数字,字符或字符串文字模式 k 与值 v 匹配成功ķ

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

例如,您的函数h

h 0 = -1
h x = x + 1

可以改写为

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

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

这里有两个关于Haskell与许多其他语言有何不同的重要观察结果:

  1. 并未针对所有类型定义相等概念。除非x == yx的类型具有{{1},否则无法询问是否y实例。
  2. 数字类型集不是固定的。数字文字可以采用任何具有Eq 实例的类型。您可以定义自己的类型并将其设为Num的实例,并且它也不一定必须具有Num的实例。所以并非所有"数字"可以比较平等。
  3. 因此,您的函数Eq的上下文不足以成为" h必须是数字。"更具体地说,上下文必须是" a必须是具有相等性测试的数字"确保有办法检查a是否等于x以执行模式匹配。