Ответ 1
Вам может понадобиться ADT, который может быть создан только с золотыми номерами чисел, а затем напишите myfun, чтобы принять этот тип данных.
Я предположил Integer как базовый тип, но вы могли бы использовать другие (например: Double или Float) или даже быть полиморфными.
1) Сделайте ADT
module Golden (Gold, getGold, buildGold) where
data Gold = G Integer Integer
getGold :: Gold -> (Integer, Integer)
getGold (G x y) = (x, y)
buildGold :: Integer -> Integer -> Maybe Gold
buildGold x y
| isGolden x y = Just (G x y)
| otherwise = Nothing
Обратите внимание, что этот модуль экспортирует тип Gold
, но не конструктор (а именно, не G
). Таким образом, единственный способ получить значение типа Gold
- с buildGold
, который выполняет проверку времени выполнения, но только один - поэтому значения Gold могут использоваться и считаться золотым коэффициентом для всех потребителей без проверка.
2) Используйте ADT для сборки myfun
myfun :: Gold -> ???
myfun g = expr
where (x, y) = getGold g
Теперь, если вы попытаетесь вызвать myfun
с не-золотым номером (значение не типа Gold
), вы получите ошибку времени компиляции.
Резюме
Для создания функции золотых чисел buildGold
должна использоваться функция, которая заставляет проверять число.
Обратите внимание, что проверяется, когда! У вас есть гарантия времени компиляции, что myfun
и все другие функции, которые вы хотите использовать с Gold
, всегда предоставляются золотыми коэффициентами. Ввод программы (от пользователя, сети или где-либо еще) все еще требует проверки времени выполнения и того, что предоставляет buildGold
; очевидно, что никогда не будет такой программы, которая может пообещать, что человек не будет вводить что-то нежелательное.
Альтернативы, приведенные в комментариях к вашему вопросу, также заслуживают рассмотрения. ADT немного тяжелый вес, если вам нужна только одна функция, myfun
, которая может выйти из строя, а затем просто myfun :: (Integer, Integer) -> Maybe ???
.