Запишите значение синтаксиса по умолчанию для средства доступа - PullRequest
9 голосов
/ 18 января 2012

Когда я писал ответ , я столкнулся с интересной проблемой:

data Gender = Male | Female
            deriving (Eq, Show)

data Age = Baby | Child | PreTeen | Adult
         deriving (Eq, Show, Ord)

data Clothing = Pants Gender Age
              | Shirt Gender Age
              | Skirt Age         -- assumed to be Female
              deriving (Show, Eq)

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

data Clothing = Pants {gender :: Gender, age :: Age}
              | Shirt {gender :: Gender, age :: Age}
              | Skirt {age :: Age}
              deriving (Show, Eq)

Проблема в том, что я хочу, чтобы gender $ Skirt foo всегда оценивалось в Female (независимо от foo, что является Age). Я могу придумать несколько способов сделать это, но они требуют, чтобы я либо

  1. использует умные конструкторы, теоретически разрешающие Skirt Male foo, но не выставляющие конструкторы
  2. определить мою собственную gender функцию

С # 1, не раскрывая конструктор в модуле, я эффективно предотвращаю использование модулем записи пользователями модуля. С # 2 я должен полностью отказаться от синтаксиса записи или определить дополнительную функцию gender', которая снова побеждает синтаксис записи.

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

Ответы [ 2 ]

0 голосов
/ 25 марта 2015

Да, между типами и данными существует напряженность ... которая, кстати, показывает, насколько тонка линия.

Практический ответ - использовать экземпляр по умолчанию, как указано в Haskell Wiki .Он точно отвечает на ваш точный вопрос, так как вы должны отказаться от прямого использования конструктора.

Таким образом, для вашего примера,

data Age = Baby | Child | PreTeen | Adult | NoAge
data Clothing = Pants {gender :: Gender, age :: Age}
              | Shirt {gender :: Gender, age :: Age}
              | Skirt {gender :: Gender, age :: Age}
              deriving (Show, Eq)

skirt = Skirt { gender=Female, age=NoAge }

, тогда разработчики могут создавать новые экземпляры со значениями по умолчанию, используя copy-andсредство обновления записи с синтаксисом записи

newSkirt = skirt { age=Adult }

и gender newSkirt оценивается как Female

Я хочу подчеркнуть, что этот подход приводит к тому, что вы определяете значения по умолчанию на уровне типа, которыйЯ думаю, что это хорошо (конечно, конструктор NoAge - это Nothing типа Maybe Age).

0 голосов
/ 03 февраля 2012

Есть ли способ использовать преимущества синтаксиса записи, а также предоставить неизменяемое значение по умолчанию для одного из моих конструкторов?

В отсутствие убедительного контрпримера ответ кажется "нет".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...