Расширяемые классы типа Haskell
Я читаю статью о программировании с зависимой типизацией и наткнулся на следующую цитату:
"[...] в отличие от классов типов Haskell, тип данных [...] закрыт ", в том смысле, что нельзя добавить новые типы в юниверс, не расширяя тип данных.
Мой новый вопрос: в каком смысле открыты классы типа Haskell? Как они растяжимы? Кроме того, каковы теоретические последствия наличия этого свойства (открытый против закрытого)?
Спасибо!
4 ответа
Учитывая класс типа как:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
... он (в основном) реализован в виде словаря:
data Monoid m = Monoid
{ mempty :: m
, mappend :: m -> m -> m
}
Примеры как:
instance Monoid [a] where
mempty = []
mappend = (++)
... переводиться в словари:
listIsAMonoid :: Monoid [a]
listIsAMonoid = Monoid
{ mempty = []
, mappend = (++)
}
... и компилятор обращается к словарю выше, когда вы используете списки в качестве Monoid
s.
Это подводит нас к вашим вопросам:
в каком смысле открыты классы типа Haskell? Как они растяжимы?
Они открыты в том же смысле, что и полиморфные значения открыты. У нас есть некоторый полиморфный тип данных:
data Monoid m = ...
... и мы можем создать экземпляр полиморфного m
Переменная типа для любого типа, где мы можем предоставить подходящие значения для mempty
а также mappend
поля.
Классы типов открыты, потому что вы можете сделать произвольный тип экземпляром этого типа. При создании класса типа вы указываете интерфейс, но не типы, которые ему принадлежат. Затем в любом коде, который включает определение класса типов, вы можете сделать его тип экземпляром, предоставляя необходимые функции из интерфейса, используя instance TypeClass type of
синтаксис.
Классы типов "открыты", потому что они всегда могут иметь больше типов, добавленных к ним "по факту", добавляя больше объявлений экземпляров. Это можно сделать даже в "клиентском" коде, который просто использует модуль, содержащий класс типа.
Ключевым моментом является то, что я могу написать код, который работает со значениями с некоторым ограничением класса типов, и тот же код без изменений можно использовать для типов, которых не было, когда я писал класс типов.
Конкретные типы данных в Haskell "закрыты" в том смысле, что этого не может быть. Если я напишу код, который работает с членами определенного типа данных (даже если он полиморфный), то вы не сможете использовать этот код для работы с новыми вещами, о которых я даже не думал, если только вы не можете изменить тип (что, вероятно, требует изменения всех мест, где он используется).
Об этом Ральф Леммел написал несколько хороших видео-лекций на 9-м канале - очень рекомендуется.