2012-06-08 8 views
7

Gibt es trotzdem eine Funktion wie die folgende in Haskell zu definieren?Haskell: Nicht-strikte boolesche Operationen

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 

ich nicht noch einen Anwendungsfall dafür haben (obwohl ich in einem interessiert sein würde), ich bin nur interessiert, wenn es möglich ist.

+0

Ist diese faule Bewertung oder Ihre Haskell-Interpretation der dreiwertigen Logik? –

+4

'undefined' ist kein Wert; Es ist die Abwesenheit eines Wertes. Daher können Sie nicht überprüfen, ob es nicht definiert ist. Sie müssen also wählen: Nummer 1, 6 und 8 oder Nummer 4, 5, 6; Du kannst nicht beides haben. – dflemstr

Antwort

12

Je nach Auswertung (in der Reihenfolge, in der Sie die Werte überprüfen) Sie eine faule Version schreiben:

Prelude> True || undefined 
True 
Prelude> undefined || True 
*** Exception: Prelude.undefined 

Prelude> :t or 
or :: [Bool] -> Bool 

Prelude> or [True, undefined] 
True 

in der Tat, die Standard-Definition in Haskell wird so verhalten, da Haskell ein faul Sprache.

Es gibt jedoch keine Möglichkeit, einen undefinierten Wert zu "überspringen", ohne zuerst den Wert zu betrachten, der ihn nach unten auswertet, was dazu führt, dass Ihr Ausdruck undefiniert ist.

Denken Sie daran, dass faule Werte sind Geschenke mit Geistern in ihnen:

enter image description here

Wenn Sie in der Box aussehen, ein Geist könnte man bekommt.

Wenn die Suche nach Böden wichtig ist (z. B. als Teil einer Testsuite), können Sie sie als Ausnahmen behandeln, and intercept them. Aber Sie würden das nicht in einer reinen Funktion tun.

+2

+1 für die Box mit dem Geist ;-) und für die Antwort zu – epsilonhalbe

+1

Als Referenz kommt die Box mit dem Geist von Edward Yang ist sehr empfehlenswert Blogpost http://blog.ezyang.com/2011/04/the -haskell-heap/ –

15

Dies ist in Standard Haskell nicht möglich, kann aber mit einem unsicheren Trick durchgeführt werden, implementiert in der lub Bibliothek von Conal Elliott.

Grundsätzlich Sie schreiben zwei Funktionen:

orL True _ = True 
orL False x = x 

orR = flip orL 

und dann kann man or a b definieren die lub (die obere Grenze in Bezug auf „Definiert“ order) zu sein und von orL a borR a b.

Betriebsmäßig führt es beide Berechnungen parallel aus und wählt die erste, die erfolgreich ist, die andere ab.

Auch wenn das funktioniert, wie Sie vorgeschlagen haben, hat es wichtige Nachteile. Zuallererst ist lub nur sicher, wenn seine Argumente übereinstimmen (gleich, es sei denn unten). Wenn Sie lub True False einnehmen, wird das Ergebnis nicht deterministisch sein und somit die Reinheit verletzen! Zweitens kann der Leistungsaufwand beim parallelen Ausführen beider Berechnungen unter bestimmten Bedingungen dominieren (versuchen Sie beispielsweise, eine foldr or False einer großen Liste zu berechnen!).

+0

Warum soll 'lub True False' nichtdeterministisch sein? intuitiv sollte es "undefined" zurückgeben. –

+0

@EarthEngine, weil das in der definierten Reihenfolge nicht monoton ist und so unmöglich zu implementieren ist. Insbesondere darf "f Falsch" nicht weniger definiert sein als "f undefiniert". Wenn du 'f = lub True' nimmst, bekommst du dein Beispiel. – Rotsor

+0

So ist es möglich zu schreiben 'lub ':: Bool -> Bool -> Vielleicht Bool' so dass' lub' Wahr Falsch == Nichts? –