Зачем в Haskell определять функцию с ограничением типа:
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
Вместо того, чтобы определять его, чтобы его тип был:
ghci> :t (==)
(==) :: Eq -> Eq -> Bool
Зачем в Haskell определять функцию с ограничением типа:
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
Вместо того, чтобы определять его, чтобы его тип был:
ghci> :t (==)
(==) :: Eq -> Eq -> Bool
Вы бы не стали делать вторую версию, потому что получили бы ошибку компиляции. Eq
- это не тип, это класс типов. Вы не можете использовать класс типов в местах, где требуется тип.
Если вы определили свой собственный тип MyEq
, а затем определили функцию ==
с типом MyEq -> MyEq -> Bool
, выражение "hello" == "hello"
было бы недопустимым, поскольку "hello"
является значением типа String, а не типа MyEq. Поскольку в haskell нет подтипов, значение не может быть одновременно типа String и типа MyEq.
Итак, если вы хотите определить функцию, которая может принимать значения разных типов, отвечающих определенным условиям, вам нужны классы типов.
let a :: Eq -> Eq -> Bool ; a b c = b == c ; in a 2 2
в ghci.
- person Aidan Cully; 29.06.2010
В Haskell «тип» может иметь только один конкретный набор возможных значений, который не пересекается ни с каким другим типом. Не бывает такого, чтобы один тип был «другим видом» или «подтипом» другого типа.
Когда нам нужен полиморфизм, т. е. функции, которые могут применяться более чем к одному типу, мы можем указать это, используя переменную типа в сигнатуре типа функции.
Но переменная типа вообще может ссылаться на любой тип. Мы не всегда знаем, как определить нашу функцию для абсолютно каждого типа. Например, функция (>)
имеет смысл только для типов, элементы которых сопоставимы. Компилятор отклонит функцию, чья сигнатура типа слишком общая, чтобы помочь нам избежать тарабарщины.
В вашем примере Eq
не является типом. Это класс типов — имя для набора типов. Мы объявляем имена классов типов, используя ключевое слово class
, и добавляем типы в класс, используя ключевое слово instance
. Назначение класса типов состоит в том, чтобы использовать его в ограничении для ограничения области действия переменной типа.
Подход Haskell к типам и полиморфизму основан на «системе типов Хиндли-Милнера». Это чрезвычайно точный, но очень выразительный способ описания данных, который упрощает предоставление компилятору огромного количества сведений о типах в вашей программе. Этот интеллект помогает компилятору автоматически определять типы, оказывать вам большую помощь в корректировке вашей программы и оптимизировать скомпилированный результат, помимо других преимуществ.
Но будьте осторожны — это сильно отличается от того, как типы используются в ООП, к чему вы, возможно, привыкли. Обычно нет прямого перевода между объектно-ориентированной программой и программой на Haskell. Вы должны думать о задаче по-другому с самого начала. Будьте особенно осторожны, чтобы не спутать понятия Haskell "класс" и "экземпляр" с совершенно другим способом использования этих слов в ООП.