Связь между различными типами в Haskell
Насколько я понимаю, в Haskell есть 4 "типа":
- Алгебраический тип данных с
data
Конструкторы типов данных (что после=
вdata
типы; не печатает технически, я не думаю)- Введите псевдоним с
type
- Типы классов с
class
- Введите экземпляры с
instance
Вопросы:
- Если в Haskell есть больше видов типов. Если да, то каковы отношения.
- Какая разница между
data
тип иclass
класс типов. Они кажутся похожими, хотя, очевидно, у них есть некоторые разные особенности. То же самое с (3). - Какая разница между
data
тип иinstance
экземпляр класса типов.
Я новичок в Хаскеле.
2 ответа
data
а также newtype
вводить новые типы (или конструкторы типов на самом деле - Maybe
не тип, но Maybe a
это тип для любого a
это тип).
data
Объявление вводит как новый тип (что осталось от =
) и способ представления данных этого типа (что является правом на =
).
Так, например, если у вас есть объявление данных, подобное этому:
data SomeType = SomeConstructor
Затем вы ввели новый тип под названием SomeType
и способ построения значений SomeType
а именно конструктор SomeConstructor
(который, кстати, не имеет никаких параметров, поэтому является единственным значением, населяющим этот тип).
Класс типов не выполняет ни одну из этих вещей (и при этом instance
). Класс типов вводит ограничение и набор полиморфных функций, которые должны быть доступны, если это ограничение выполнено. instance
в основном говорит "этот тип соответствует этому ограничению", предоставляя реализацию для этих функций. Так что class
на самом деле не вводит новые типы, это просто способ обеспечить специальный полиморфизм для существующих типов.
Например, Show
Класс типов примерно такой:
class Show a where -- a is an instance of Show if
show :: a -> String -- it has a function called show with this signature
(Обратите внимание, что фактическое Show
класс в Prelude
не совсем так выглядит)
show
теперь имеет тип Show a => a -> String
, который вы можете прочитать как
для всех, если они соответствуют ограничению
Show
(или, в качестве альтернативы, если они являютсяShow
) это функция, которая принимаетa
и возвращает строку
Пример для этого будет выглядеть так
instance Show SomeType where
show SomeConstructor = "SomeConstructor"
Что значит
SomeType
удовлетворяет ограничениюShow
, и я покажу вам, как обеспечить реализациюshow
Это примерно суть этого. Существуют языковые расширения, которые позволяют более сложным вещам происходить с классами типов и экземплярами, но пока вам не нужно об этом беспокоиться.
Возможно, вы слышали о видах, которые являются "типами типов" в Haskell. Тип это что-то доброе *
, который представляет вещи, которые могут иметь значения:
> :kind Int
Int :: *
> :kind Char
Char :: *
Конструкторы типов - это вещи с добром * -> *
; конструктор типа принимает тип (что-то вроде *
) и возвращает другой тип.
> :kind Maybe
Maybe :: * -> *
> :kind []
[] :: * -> *
Применение конструктора типов дает вам новую вещь *
:
> :kind Maybe Int
Maybe Int :: *
> :kind [] Float
[] Float :: *
(Парсер позволяет [Foo]
как особый случай для [] Foo
.)
Есть и другие вещи, которые тоже виды. Один из них является Constraint
и вы создаете Constraint
с конструктором ограничения (иначе известный как класс типа). Присвойте конструктору ограничения тип, и вы получите ограничение.
> :kind Show
Show :: * -> Constraint
> :kind Show Int
Show Int :: Constraint
> :kind Show (Int -> Char)
Show (Int -> Char) :: Constraint
(Обратите внимание, что последний правильно родил, хотя ни один экземпляр для Int -> Char
определено.)
В этом свете, =>
выглядит как оператор, а не просто специальный синтаксис. Его аргументы - это "список" ограничений (хотя и использующий универсально квантифицированные переменные типа вместо конкретных типов) и тип, а его возвращаемое значение является "ограниченным" типом (давайте представим, что есть тип ConstrainedType
в дополнение к *
, * -> *
, а также Constraint
).
:t show
show :: Show a => a -> String
-- Taking extreme liberties with syntax
-- :k (=>)
-- (=>) :: [Constraint] -> * -> ConstrainedType
-- A section?
-- :k (Show a =>)
-- (Show a =>) :: * -> ConstrainedType
-- :k (Showa => * -> String)
-- Show a => a -> String :: ConstrainedType