En GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
¿Por qué el primero no es una excepción anidada?
En GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
¿Por qué el primero no es una excepción anidada?
error
es especial y no es realmente un mecanismo de excepción. Para ver excepciones reales y capturables, consulte Error
mónada.
(\f g x -> f (g x)) error error ""
comporta de manera diferente a (.) error error ""
, aunque esa función es equivalente a (.)
. Tal vez tenga que ver con los indicadores de optimización con los que se compiló Prelude.
iterate error "" !! n
y lo impresionante fix error
.
error = error
y programo en consecuencia.
Respuestas:
La respuesta es que esta es la semántica (algo sorprendente) de las excepciones imprecisas
Cuando se puede mostrar que el código puro evalúa un conjunto de valores excepcionales (es decir, el valor de error
o undefined
, y explícitamente no el tipo de excepciones generadas en IO ), entonces el lenguaje permite que se devuelva cualquier valor de ese conjunto. Los valores excepcionales en Haskell se parecen más NaN
al código de punto flotante que a las excepciones basadas en el flujo de control en los lenguajes imperativos.
Un problema ocasional incluso para los Haskellers avanzados es un caso como:
case x of
1 -> error "One"
_ -> error "Not one"
Dado que el código evalúa un conjunto de excepciones, GHC es libre de elegir una. Con las optimizaciones activadas, es posible que descubra que esto siempre se evalúa como "Ninguno".
¿Por qué hacemos esto? Porque de lo contrario restringiríamos demasiado el orden de evaluación del lenguaje, por ejemplo, tendríamos que fijar un resultado determinista para:
f (error "a") (error "b")
por ejemplo, requiriendo que se evalúe de izquierda a derecha si hay valores de error presentes. ¡Muy poco Haskelly!
Dado que no queremos paralizar las optimizaciones que se pueden hacer en nuestro código solo para brindar soporte error
, la solución es especificar que el resultado es una elección no determinista del conjunto de valores excepcionales: ¡excepciones imprecisas! En cierto modo, se devuelven todas las excepciones y se elige una.
Normalmente, no le importa, una excepción es una excepción, a menos que le importe la cadena dentro de la excepción, en cuyo caso usar error
para depurar es muy confuso.
Referencias: Una semántica para excepciones imprecisas , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Diseño e implementación de lenguajes de programación Proc (PLDI'99), Atlanta. ( PDF )
throw
) y con los que puedes lanzar una excepción de manera determinista throwIO
.
case error "banana" of (x:xs) -> error "bonobo"
puedo darte * Exception: bonobo
.