2012-06-08 16 views
7

¿Hay alguna forma de definir una función como la siguiente en Haskell?Haskell: operaciones booleanas no estrictas

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 

que actualmente no tienen un caso de uso para ello (aunque estaría interesado en uno), sólo estoy interesado si es posible.

+0

¿Es esta evaluación perezosa o su interpretación de Haskell de la lógica de tres valores? –

+4

'undefined' no es un valor; es la ausencia de un valor. Por lo tanto, no puede "verificar si no está definido", por lo que debe elegir: número 1, 6 y 8 o número 4, 5, 6; no puedes tener ambos. – dflemstr

Respuesta

12

En función de su orden de evaluación (el orden en que se inspecciona valores) se puede escribir una versión perezoso:

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

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

Prelude> or [True, undefined] 
True 

de hecho, la definición por defecto en Haskell se comportará como éste, ya que Haskell es un vago idioma.

Sin embargo, no hay manera de "omitir" un valor indefinido, sin mirar primero el valor, que lo evaluará en la parte inferior, lo que hace que su expresión no esté definida.

Recuerde que los valores son perezosos presentes con fantasmas dentro de ellos:

enter image description here

Si nos fijamos en el interior de la caja, un fantasma podría obtener.

Si la comprobación de fondos es importante (por ejemplo, como parte de una suite de pruebas) puede tratarlos como excepciones, and intercept them. Pero no harías eso en una función pura.

+2

+1 para la caja con el fantasma ;-) y para la respuesta también – epsilonhalbe

+1

Como referencia, la caja con el fantasma proviene de la muy recomendable publicación de blog de Edward Yang http://blog.ezyang.com/2011/04/the -haskell-heap/ –

15

Esto no es posible en Haskell estándar, pero se puede hacer con un truco inseguro, implementado en la biblioteca lub de Conal Elliott.

Básicamente, se escribe dos funciones:

orL True _ = True 
orL False x = x 

orR = flip orL 

y luego se pueden definir or a b ser el lub (la menor cota superior con respecto a la orden "definedness") de orL a b y orR a b.

Operativamente, ejecuta ambos cálculos en paralelo y elige el primero que tiene éxito, matando al otro.

Aunque eso funciona como lo propuso, tiene desventajas importantes. En primer lugar, lub solo es seguro si sus argumentos coinciden (igual a menos que sea inferior). Si toma lub True False, el resultado será no determinista, lo que viola la pureza. En segundo lugar, la sobrecarga de rendimiento de ejecutar ambos cálculos en paralelo puede llegar a ser dominante en algunas condiciones (¡trate de calcular un foldr or False de una lista grande, por ejemplo!).

+0

¿por qué 'lub True False' no será determinista? intuitivamente, debería devolver 'undefined'. –

+0

@EarthEngine, porque eso no es monotónico en el orden de definición y por lo tanto es imposible de implementar. En particular, 'f False' no puede estar menos definido que' f undefined'. Si tomas 'f = lub True', obtienes tu ejemplo. – Rotsor

+0

Entonces, ¿es posible escribir 'lub ':: Bool -> Bool -> Maybe Bool' tal que' lub' True False == Nothing'? –

Cuestiones relacionadas