Выбор между классом и записью

Основной вопрос: каким принципам проектирования следует придерживаться при выборе между использованием класса или использованием записи (с полиморфными полями)?

Во-первых, мы знаем, что классы и записи по сути эквивалентны (поскольку в Core классы обесцениваются до словарей, которые являются просто записями). Тем не менее, есть отличия: классы передаются неявно, записи должны быть явными.

Если заглянуть немного глубже, классы действительно полезны, когда:

  1. у нас есть много разных представлений «одного и того же», и
  2. при фактическом использовании, какое представление используется, можно сделать вывод .

Классы неудобны, когда у нас есть (вплоть до параметрического полиморфизма) только одно представление наших данных, но у нас есть несколько экземпляров.Это приводит к синтаксическому шуму из-за необходимости использовать newtype для добавления дополнительных тегов (которые существуют только в нашем коде, поскольку мы знаем, что такие теги стираются во время выполнения), если мы не хотим включать все разновидности проблемных расширений (например, перекрывающиеся и / или неразрешимые экземпляры).

Конечно, все становится еще запутаннее: что, если я хочу иметь ограничения на свои типы? Давайте возьмем реальный пример:

class (Bounded i, Enum i) => Partition a i where
    index :: a -> i

Я мог бы так же легко сделать

data Partition a i = Partition { index :: a -> i}

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

Есть ли рекомендации по дизайну, которые могут мне помочь?

33
задан Jacques Carette 12 November 2011 в 18:56
поделиться