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 является ленивым языком.

однако нет способа "пропустить" неопределенное значение, не посмотрев сначала на значение, которое будет оценивать его снизу, что приводит к тому, что ваше выражение не определено.

помните, что ленивые значения представлены с призраки внутри них:

enter image description here

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

Если проверка днищ важна (например, как часть 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 большого списка, например!).