Записи Haskell, более чистый подход?

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

Я понимаю, что вы можете обойти это, имея отдельные модули, но я не хотел этого делать и вместо этого пытался использовать этот подход:

class HasX a where
  x :: a -> X

data D1 = D1 { d1_x :: X, ... }
instance HasX D1 where
  x = d1_x

data D2 = D2 { d2_x :: X, ... }
instance HasX D2 where
  x = d2_x

(Это только делает, а не устанавливает, я, конечно, должен написать больше кода для выполнения наборов).

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

Есть ли библиотека или расширение для GHC, что делает такой подход менее беспорядочным для записи?

Ответ 1

Кажется, Data.Has инкапсулирует много того, что вы ищете. В своем словаре они считают, что их класс типа Knows ближе к вашему Has, а также обеспечивает подпись для инъекций.

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

Для удобства также существует некоторая поддержка, предоставляющая генератор экземпляра Has с шаблоном Haskell в Has-TH

Вы можете найти больше ярлыков типа и других материалов, относящихся к записи, в работах Олега Типа, например OOHaskell (также с Ральфом Леммелем).

Ответ 2

data-accessor-template может по крайней мере помогать писать приемники set/get. Возможно, некоторые люди могут придумать код шаблона Haskell для генерации классов и экземпляров для каждого имени поля записи. Однако я сам не использую материал Template Haskell. Он ограничивает вас GHC и даже конкретными версиями GHC, поскольку Template Haskell меняет разные версии GHC. Наличие одной (основной) записи для каждого модуля действительно окупается.