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 отличается от многих других языков:

  1. Понятие равенства не определено для всех типов. Нельзя спрашивать, x == y если тип x а также y имеет Eq пример.
  2. Набор числовых типов не является фиксированным. Числовой литерал может принимать любой тип, имеющий экземплярNum, Вы можете определить свой собственный тип и сделать его экземпляром Numи он не обязательно должен иметь экземпляр Eq, Так что не все "числа" можно сравнить на равенство.

Так что это недостаточно для контекста вашей функции h быть "a должен быть числом."Контекст должен быть, более конкретно, "a должно быть число с проверкой на равенство ", чтобы убедиться, что есть способ проверить, x равно 0 для того, чтобы выполнить сопоставление с образцом.

Другие вопросы по тегам