Ответ 1
Да, не нужно экспортировать конструктор данных из модуля.
Вместо этого вы экспортируете функцию, которая выполняет проверку, как вы сказали. Это часто называют интеллектуальный конструктор.
Я хотел бы создать новый интегральный тип, ограниченный определенным диапазоном. Я пробовал:
data PitchClass = PC Int deriving (Ord, Eq, Show)
instance Bounded PitchClass where
minBound = PC 0
maxBound = PC 11
Однако я хочу, чтобы что-то не получилось, если что-то вроде
PC 12
или
PC (-1)
.
Является общим подходом к ситуации, в которой вы хотите установить ограничения на создание новых типов, в которых конструкторы значения не экспортируются из модуля, а скорее функции, возвращающие экземпляры типа и выполняющие проверки ограничений, экспортируются
Да, не нужно экспортировать конструктор данных из модуля.
Вместо этого вы экспортируете функцию, которая выполняет проверку, как вы сказали. Это часто называют интеллектуальный конструктор.
Альтернативное решение для случаев, когда количество полных значений является малым, состоит в простом перечислении возможных конструкторов.
data PitchClass = A | Bb | B | C | Db | D | Eb | E | F | Gb | G | Ab
deriving (Eq, Ord, Bounded, Show, Read)
Есть полдюжины разных хаков, которые вы можете попробовать отсюда, чтобы сделать его более удобным по-разному; например, вы можете получить Enum
, чтобы получить toEnum . fromEnum = id
(и toEnum (-1) = {- an exception -}
), или вы можете написать собственный экземпляр Integral
, чтобы получить 0 = A
(и ваш выбор поведения для -1
).