Но потом я понял, что (a, Api a) должен иметь возможность полностью скрыть a, поскольку никому нет до этого дела, и тогда Api превращается в простую запись типов данных, а не функций.
Точно! Использование экзистенциала, подобного тому, когда это делает простой тип данных, называется экзистенциальный класс типов антипаттерна (см. Также FAQ ). Однако это не имеет прямого отношения к лени; Вы можете так же легко представить каждое поле, как () -> Result
на строгом языке. Конечно, использовать его было бы не так хорошо.
Преимущество класса типов заключается в неявном неявном, направленном на тип разрешении : вы можете просто использовать операции напрямую, как если бы они были мономорфными для определенных типов, которые вы используете, и это работает хорошо, без необходимости придумывать отдельное имя для каждого типа, для которого вы хотите реализовать операцию. Для примера того, почему классы типов ценны, представьте, был ли Num реализован как запись; Вы должны будете передать запись реализации для каждого типа везде. Хуже того, нет места для fromInteger :: (Num a) => Integer -> a
, так как он полиморфен в результате и вообще не принимает значения типа a
!
Другой пример - что-то вроде Орд. Вы не можете представлять Ord как запись, потому что любой экземпляр Ord должен оперировать теми же значениями, которые исключаются этим преобразованием класса типа в запись. Наличие Ord в качестве класса типов также позволяет нам писать код, который является универсальным для любого типа значения, которое можно упорядочить, что действительно очень ценно, и в этом отношении использование классов типов, безусловно, в некоторой степени напоминает интерфейсы ООП *. 1020 *
Однако, когда нет реальных релевантных значений, о которых можно говорить, или они все приходят «извне» просто для того, чтобы действовать как внутреннее состояние (например, экзистенциальное), класс типов просто добавляет ненужный шаблон и гораздо меньше «сначала». учебный класс". Функции и типы данных являются реальными единицами абстракции в Haskell; Типовые классы - это просто удобство.
Итак, достаточно ли он умен (или мог бы) понять, что ему вообще не нужно создавать значение Api, поскольку все, что нам нужно, - это вызов myf2 для значения MyData?
GHC, вероятно, создаст промежуточный тип данных, но вам не стоит слишком беспокоиться; экзистенциальный также содержит словарь экземпляров класса типов, который похож на ваш тип Api. Преимущество этого интерфейса записи на самом деле не в производительности, а в простоте, ясности и компоновке (легко преобразовать все поля записи для создания «модифицированной» реализации - но у вас не может быть функции, которая преобразует тип). экземпляр класса).