Когда мне следует определять полиморфные функции по классам типов или какими-либо другими способами?
Я пытаюсь выяснить назначение класса типов, и что еще есть, если не использовать тип класса.
Является ли класс типов способом определения полиморфных функций?
Является ли класс типов единственным способом определения полиморфных функций? Например:
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
instance Eq Bool where
False == False = True
True == True = True
_ == _ = False
Могу ли я определить ==
а также /=
за Bool
(и любой другой тип) без использования класса типа Eq
?
Где есть какой-то другой способ, когда я должен использовать какой-либо способ определения полиморфных функций, используя класс типов или другой способ?
3 ответа
Вы всегда можете написать неограниченную полиморфную функцию, которая не требует никакого класса типов. Простой пример
length :: [a] -> Int
- это работает без класса типов, и (ну, потому что) это работает для любого типа a
бы то ни было. А именно, length
на самом деле не важно, какие значения в этом списке, а только структура, в которой содержатся эти значения. На самом деле он никогда ничего не делает с этими значениями, и полиморфный тип фактически гарантирует это.
Если нужная вам полиморфная задача имеет такую форму, то есть тип, к которому вы на самом деле не нуждаетесь, вы просто знаете, что она есть, тогда вам не следует писать / вызывать класс типов, просто используйте параметрический полиморфизм в стиле ML, как в length
, Однако довольно часто вам нужно получить доступ к самим значениям, осмотреть их каким-либо образом. Для этого существуют классы типов, не ограничивающие вас конкретным конкретным типом. Eq
, как вы сами цитировали, является примером.
Является ли класс типов способом определения полиморфных функций?
Да, это способ. Но не единственный способ. Например, параметрический полиморфизм просто означает, что если вы определите функцию, как init :: [a] -> [a]
, это будет работать для любого a
, Классы типов используются для специального полиморфизма: в зависимости от типа реализация может быть совершенно другой. Это в отличие от параметрического полиморфизма, где head
Функция всегда одинакова, независимо от типа a
,
Является ли класс типов единственным способом определения полиморфных функций?
Нет, см. Предыдущий раздел.
Могу ли я определить
==
а также/=
заBool
(и любой другой тип) без использования класса типаEq
?
Это зависит от того, является ли реализация одинаковой для всех типов или нет. Вы можете использовать -XNoImplicitPrelude
флаг, чтобы избежать импорта Prelude
, а затем вы можете определить свой собственный (==)
функция.
Существует разница между полиморфными функциями в ООП и в Хаскеле, я говорю это, потому что термин "полиморфизм" обычно используется в ООП.
Функции над списком, например, полиморфны:
cons:: a -> [a] -> [a]
cons x xs = x:xs
где a - полиморфный тип, и там нет класса типов.
Кстати, есть способ быстро реализовать классы типов по умолчанию, такие как Eq
или же Show
, например:
data MBool = MTrue | MFalse deriving (Eq, Show)
Итак, разница в том, что класс типов является ограничением, представьте эту функцию со списками:
mapShow :: Show a => [a] -> [String]
mapShow = map show
Это отличается, потому что теперь, ограничено, это не может быть "а". Следует реализовать класс типов Show
,
В заключение вы можете видеть, что a
печатать cons
функция является более общей или абстрактной, чем Show => a -> a
печатать mapShow
функция.