Используя типы Haskell для замены операторов контроля или если регистрации других языков

Извините, если вопрос очень элементарен, я все еще очень плохо знаком с Haskell. Позволяет говорят, что у меня есть функция, которая может только работать с двумя числами, которые находятся в золотой порции (1.618), как я определяю типы myfun x y для взятия только чисел золотого сечения. Что происходит, если я вызываю myfun без чисел золотого сечения из моей программы (ошибка компиляции?)? Что происходит, если вызов без чисел золотого сечения выполняется во времени выполнения через ввод данных пользователем?

13
задан Don Stewart 20 April 2011 в 04:31
поделиться

3 ответа

Вам может понадобиться 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 ??? .

18
ответ дан 1 December 2019 в 20:42
поделиться

Самый простой метод - использовать интеллектуальные конструкторы , которые используют функцию от Int до GoldenInt, которая проверяет, находятся ли ваши значения в требуемых соотношениях.

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

Ответ Тома выше является примером этой идиомы.

10
ответ дан 1 December 2019 в 20:42
поделиться

Лучшее, что вы можете сделать на практике, - это проверка во время выполнения. Могут быть какие-то вычисления на уровне типов, которых я не знаю (см. Комментарий Луки), но это не практично в Haskell.

Вы можете использовать утверждение , которое вы хотите заменить,

checker :: a -> b -> Bool
checker x y = x * 1.618 `approxEqual` y

unsafeMyfun :: a -> b -> c
unsafeMyfun x y = assert (checker x y) (doRealThingWith a b)

или вернуть Может быть (или Либо ошибитесь ), чтобы избегайте исключений, которые не могут быть обнаружены в чистых функциях

myfun :: a -> b -> Maybe c
myfun x y = do
              guard $ checker x y
              return $ doRealThingWith x y

, или используйте настраиваемый тип контракта, как в ответе Тома и т. д. В любом случае невозможно проверить ограничение во время компиляции . Фактически, из-за монады ввода-вывода любое ограничение времени компиляции не может быть точным.

1
ответ дан 1 December 2019 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: