Возможно, вы захотите 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
), вы получите ошибку времени компиляции.
Recap
Для построения золотых чисел должна использоваться функция buildGold
, которая заставляет проверять число.
Обратите внимание, что проверяется, когда! У вас есть гарантия времени компиляции, что myfun
и все другие функции, которые вы хотите использовать с Gold
, всегда имеют золотые отношения. Ввод программы (от пользователя, сети или где-либо еще) все еще нуждается в проверках во время выполнения, и это то, что обеспечивает buildGold
; очевидно, никогда не будет программы, которая может обещать, что человек не будет печатать что-то нежелательное.
Альтернативы, приведенные в комментариях к вашему вопросу, также заслуживают рассмотрения. ADT имеет небольшой вес, если вам нужна только одна функция, myfun
, которая может дать сбой, тогда просто наберите myfun :: (Integer, Integer) -> Maybe ???
.