Я часто сталкиваюсь с проблемой при написании больших программ в Haskell. Я часто нахожусь в нескольких разных типах, которые имеют внутреннее представление и несколько основных операций.
Существует два относительно очевидных подхода к решению этой проблемы.
Один использует класс типа и расширение GeneralizedNewtypeDeriving
. Положите достаточную логику в класс типа, чтобы поддерживать общие операции, которые желает использовать прецедент. Создайте тип с желаемым представлением и создайте экземпляр класса типа для этого типа. Затем для каждого варианта использования создайте обертки для него с помощью newtype и выведите общий класс.
Другой - объявить тип с переменной типа phantom, а затем использовать EmptyDataDecls
для создания разных типов для каждого другого варианта использования.
Моя главная проблема - не смешивать значения, которые разделяют внутреннее представление и операции, но имеют разные значения в моем коде. Оба этих подхода решают эту проблему, но чувствуют себя значительно неуклюжими. Моя вторая проблема заключается в сокращении количества требуемого шаблона, и оба подхода достаточно хорошо подходят для этого.
Каковы преимущества и недостатки каждого подхода? Есть ли техника, которая подходит ближе к тому, что я хочу, обеспечивая безопасность типов без кода шаблона?