Haskell: сопоставление с образцом на типах Num
Почему 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 ответ
Из отчета Haskell 2010, раздел " Неофициальная семантика сопоставления с образцом":
Сопоставление числового, символьного или строкового литерального шаблона k со значением v завершается успешно, если v
==
К
Поэтому, когда вы используете литерал (например, 0
) как образец, его значение зависит от ==
(метод Eq
учебный класс).
Например, ваша функция h
h 0 = -1
h x = x + 1
может быть переписан как
h x | x == 0 = -1
h x = x + 1
Вы (неявно) используете ==
метод, поэтому вам нужно Eq
ограничение.
Здесь есть два важных замечания о том, как Haskell отличается от многих других языков:
- Понятие равенства не определено для всех типов. Нельзя спрашивать,
x == y
если типx
а такжеy
имеетEq
пример. - Набор числовых типов не является фиксированным. Числовой литерал может принимать любой тип, имеющий экземпляр
Num
, Вы можете определить свой собственный тип и сделать его экземпляромNum
и он не обязательно должен иметь экземплярEq
, Так что не все "числа" можно сравнить на равенство.
Так что это недостаточно для контекста вашей функции h
быть "a
должен быть числом."Контекст должен быть, более конкретно, "a
должно быть число с проверкой на равенство ", чтобы убедиться, что есть способ проверить, x
равно 0
для того, чтобы выполнить сопоставление с образцом.