Haskell:Num类型上的模式匹配 [英] Haskell: pattern matching on Num types
问题描述
如果没有我们将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与许多其他语言的区别,这里有两个重要的观察结果:
- 并非所有类型都定义了相等性概念.除非
x
和y
的类型具有Eq
实例,否则无法询问x == y
. - 数字类型集不是固定的.数字文字可以接受任何具有
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:
- The notion of equality is not defined for all types. One cannot ask whether
x == y
unless the type ofx
andy
has anEq
instance. - 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 ofNum
, and it doesn't necessarily have to also have an instance ofEq
. 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屋!