2012-06-08 2 views
7

Есть ли способ определить функцию, подобную следующей в 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 

я в настоящее время не имеют прецедента для него (хотя я был бы заинтересован в одном), я просто интересно, если это возможно.

+0

Является ли эта ленивая оценка или ваша интерпретация хакелла трехзначной логикой? –

+4

'undefined' не является значением; это отсутствие ценности. Поэтому вы не можете «проверить, не определено ли это», поэтому вам нужно выбрать: номер 1, 6 и 8 или номер 4, 5, 6; вы не можете иметь обоих. – dflemstr

ответ

12

В зависимости от вашего заказа оценки (порядок, в котором вы проверяете значения), вы можете написать ленивую версию:

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

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

Если проверка на днище важна (например, как часть testuite), вы можете рассматривать их как исключения, and intercept them. Но вы не сделали бы этого в чистой функции.

+2

+1 для коробки с призраком ;-) и для ответа слишком – epsilonhalbe

+1

Для справки, коробка с призраком поступает из рекомендованного блога Эдварда Янга http://blog.ezyang.com/2011/04/the -haskell-heap/ –

15

Это невозможно в стандартном Haskell, но это может быть сделано с небезопасным трюком, реализованным в библиотеке lub от Conal Elliott.

В принципе, вы написать две функции:

orL True _ = True 
orL False x = x 

orR = flip orL 

, а затем вы можете определить or a b быть lub (верхняя грань по отношению к «» порядка определенность) из orL a b и orR a b.

Оперативно он выполняет оба вычисления параллельно и выбирает первый, который преуспевает, убивая другого.

Несмотря на то, что это работает так, как вы предложили, у него есть важные недостатки. Прежде всего, lub является безопасным только в том случае, если его аргументы согласуются (равными, если только дно). Если вы возьмете lub True False, результат будет недетерминированным, что нарушит чистоту! Во-вторых, накладные расходы на производительность при одновременном выполнении обоих вычислений могут стать доминирующими в некоторых условиях (попробуйте, например, вычислить большого списка!).

+0

Почему 'lub True False' не детерминирован? интуитивно, он должен возвращать 'undefined'. –

+0

@ EarthEngine, потому что это не монотонно в порядке определения и поэтому невозможно реализовать. В частности, 'f False' не разрешается быть менее определенным, чем' f undefined'. Если вы берете 'f = lub True', вы получите свой пример. – Rotsor

+0

Так можно ли написать 'lub ':: Bool -> Bool -> Maybe Bool', что' lub' True False == Nothing'? –

Смежные вопросы