Haskell: нестрогие логические операции
есть ли в любом случае определить функцию, подобную следующей в Haskell?
or True True = True
or True undefined = True
or True False = True
or undefined True = True
or undefined False = undefined
or undefined undefined = undefined
or False True = True
or False undefined = undefined
or False False = False
в настоящее время у меня нет прецедента для него (хотя мне было бы интересно), мне просто интересно, возможно ли это.
2 ответов
в зависимости от вашего порядка оценки (порядка, в котором вы проверяете значения) вы можете написать ленивую версию:
Prelude> True || undefined
True
Prelude> undefined || True
*** Exception: Prelude.undefined
Prelude> :t or
or :: [Bool] -> Bool
Prelude> or [True, undefined]
True
фактически, определение по умолчанию в Haskell будет вести себя так, поскольку Haskell является ленивым языком.
однако нет способа "пропустить" неопределенное значение, не посмотрев сначала на значение, которое будет оценивать его снизу, что приводит к тому, что ваше выражение не определено.
помните, что ленивые значения представлены с призраки внутри них:
Если вы посмотрите внутри коробки, призрак может сделать вас.
Если проверка днищ важна (например, как часть testsuite) , вы можете рассматривать их как исключения,и перехватить их. Но вы не сделали бы этого в чистой функции.
это невозможно в стандартном Haskell, но может быть сделано с небезопасным трюком, реализованным в или библиотека Конэла Эллиота.
в основном, вы пишете две функции:
orL True _ = True
orL False x = x
orR = flip orL
и тогда вы можете определить or a b
быть lub
(наименьшую верхнюю границу по отношению к "definedness" порядке)orL a b
и orR a b
.
Operationally, он запускает оба вычисления параллельно и выбирает первый, который преуспевает, убивая другой.
хотя это работает, как вы предложили, у него есть важные недостатки. Прежде всего,lub
безопасно, только если его аргументы согласны (равны, если внизу). Если вы берете lub True False
результат будет недетерминированным, тем самым нарушив чистоту! Во-вторых, накладные расходы на выполнение обоих вычислений параллельно могут стать доминирующими в некоторых условиях (попробуйте вычислить foldr or False
большого списка, например!).