Расширяемые классы типа Haskell
Я читаю статью о программировании с надписью и набираю следующую цитату:
"[...] в отличие от классов типа Haskell, тип данных [...] закрыт" в том смысле, что нельзя добавлять новые типы во вселенную без расширения тип данных.
Мой вопрос о новичке: в каком смысле классы типа Haskell open? Как они расширяемы? Кроме того, каковы теоретико-теоретические последствия наличия этого свойства (open vs closed)?
Спасибо!
Ответы
Ответ 1
Учитывая класс типа like:
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
.
Ответ 2
Классы классов открыты, потому что вы можете сделать произвольный тип экземпляром. Когда вы создаете класс типа, вы указываете интерфейс, но не типы, которые принадлежат ему. Затем в любом коде, который включает определение typeclass, вы можете сделать свой экземпляр своего типа, предоставляя необходимые функции из интерфейса, используя синтаксис instance TypeClass type of
.
Ответ 3
Типы классов являются "открытыми", потому что у них всегда может быть больше типов, добавленных к ним "после факта" путем добавления дополнительных объявлений экземпляров. Это можно сделать даже в "клиентском" коде, который просто использует модуль, содержащий класс типа.
Ключевым моментом является то, что я могу написать код, который работает с значениями с некоторым ограничением типа-типа, и тот же код без каких-либо изменений может использоваться для типов, которые не существовали, когда я писал класс типа.
Конкретные типы данных в Haskell "закрыты" тем, что этого не может быть. Если я пишу код, который работает с членами определенного типа данных (даже если он является полиморфным), то вы не можете использовать этот код для работы над новыми видами вещей, о которых я не думал, если вы не можете изменить тип (который, вероятно, требует изменения всех мест, где он используется).
Ответ 4
Ральф Леммель имеет очень хорошие видео-лекции по Channel9 об этом - настоятельно рекомендуется.