2012-06-08 13 views
7

Esiste comunque una funzione come la seguente in Haskell?Haskell: Operazioni booleane non rigide

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 

Io non hanno attualmente un caso d'uso per esso (anche se mi sarei interessato a uno), io sono solo interessati se è possibile.

+0

È questa valutazione lenta o l'interpretazione haskell della logica a tre valori? –

+4

'undefined' non è un valore; è l'assenza di un valore. Pertanto, non è possibile "verificare se non è definito", quindi è necessario scegliere: numero 1, 6 e 8 o numero 4, 5, 6; non puoi averli entrambi – dflemstr

risposta

12

A seconda del vostro ordine di valutazione (l'ordine in cui si ispezionare i valori) si può scrivere una versione pigra:

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

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

Prelude> or [True, undefined] 
True 

infatti, la definizione di default in Haskell si comporterà come tale, dal momento che Haskell è un pigro linguaggio.

Tuttavia, non c'è modo di "saltare" un valore non definito, senza guardare prima il valore, che lo valuterà in un fondo, il che fa sì che l'espressione non sia definita.

Ricordate che i valori pigri sono presenti con i fantasmi al loro interno:

enter image description here

Se si guarda all'interno della scatola, un fantasma potrebbe ottenere.

Se il controllo dei fondi è importante (ad esempio come parte di una suite di test), è possibile considerarli come eccezioni, and intercept them. Ma non lo faresti in una pura funzione.

+2

+1 per la scatola con il fantasma ;-) e anche per la risposta – epsilonhalbe

+1

Per riferimento, la scatola con il fantasma viene dal blog post altamente consigliato di Edward Yang http://blog.ezyang.com/2011/04/the -haskell-heap/ –

15

Questo non è possibile in Haskell standard, ma può essere eseguito con un trucco non sicuro, implementato nella libreria lub da Conal Elliott.

In sostanza, si scrive due funzioni:

orL True _ = True 
orL False x = x 

orR = flip orL 

e quindi si può definire or a b essere il lub (l'estremo superiore rispetto all'ordine "definedness") del orL a b e orR a b.

Operativamente, esegue entrambi i calcoli in parallelo e sceglie il primo che riesce, uccidendo l'altro.

Anche se ciò funziona come hai proposto, ha importanti svantaggi. Prima di tutto, lub è sicuro solo se i suoi argomenti sono d'accordo (uguale se non in basso). Se prendi lo lub True False, il risultato sarà non deterministico, violando così la purezza! In secondo luogo, il sovraccarico delle prestazioni nell'esecuzione di entrambi i calcoli in parallelo può diventare dominante in alcune condizioni (prova a calcolare un foldr or False di un elenco di grandi dimensioni, ad esempio!).

+0

perché "lub True False" non è deterministico? intuitivamente, dovrebbe restituire "undefined". –

+0

@EarthEngine, perché non è monotona nell'ordine di definizione e quindi è impossibile da implementare. In particolare, 'f False' non può essere definito con meno di' f undefined'. Se prendi 'f = lub True', ottieni il tuo esempio. – Rotsor

+0

Quindi è possibile scrivere 'lub ':: Bool -> Bool -> Forse Bool' tale che' lub' True False == Nothing'? –

Problemi correlati