Подтвердить что ты не робот

Как организовать модули Haskell с экземплярами: придерживаться типа данных vs type class?

Общий вопрос: какая структура модуля более удобна при добавлении экземпляров для существующих объектов? Какие плюсы и минусы существуют?

Скажем, я хочу добавить экземпляр NFData для типа Seq. Я могу разместить его в:

  • Data.Sequence.Extra (как то же самое делается в пакете vty)
  • Data.Sequence.Instances.NFData (точнее)
  • Control.DeepSeq.Instances
  • Control.DeepSeq.Instances.Sequence

Это случай, когда я не владею ни классом типа, ни типом данных. Другая распространенная ситуация - когда я владею классом типа типа и хочу добавлять экземпляры для типов данных из некоторого "тяжелого" пакета из Hackage, например OpenGL. Скажем, класс типа I, который я разработал, очень легкий и не имеет прямого отношения к OpenGL. Я не хочу, чтобы мой тип-класс зависел от "тяжелого" пакета, поэтому я хочу разместить экземпляры OpenGL в отдельном модуле (это мое интуитивное чувство, если у вас есть другое мнение, давайте обсудим его). Итак, каким должен быть этот модуль:

  • MyClass.Instances.OpenGL
  • Graphics.Rendering.OpenGL.Extra (вместе с экземплярами для других классов)
  • Graphics.Rendering.OpenGL.Instances.MyClass

Что более гибкое решение? В какой-то момент OpenGL можно заменить другой библиотекой, иначе MyClass можно будет заменить. Есть ли тонкие нюансы?

Кроме того, какая схема лучше, если выбрать вариант MyClass.Instances:

  • MyClass.Class для самого класса и базовых экземпляров, а модуль MyClass реэкспортирует его (и, возможно, MyClass.Instances)
  • MyClass для класса и базовых экземпляров, а MyClass.All реэкспортирует все
  • MyClass модуль для класса и базовых экземпляров и модуль для реэкспорта.
4b9b3361

Ответ 1

Обычный процесс определения места размещения экземпляра выглядит примерно так:

  • Если вы создаете новый тип данных и хотите иметь экземпляр для существующего класса:

    Поместите экземпляр в тот же модуль, что и тип данных.

  • Если вы создаете новый класс типа и хотите создавать экземпляры для существующих типов.

    Поместите экземпляры в том же модуле, что и класс типа.

  • И тип типа, и тип данных уже существуют (ваш случай).

    Если экземпляр достаточно общий, я должен связаться с автором либо типа или типа данных, либо попытаться убедить их добавить экземпляр в свой пакет.

    В противном случае создайте обертку newtype и напишите для нее экземпляр.

    Только в качестве крайней меры рассмотрите возможность создания сиротского экземпляра.