[Haskell-cafe] ($) not as transparent as it seems
daniel.is.fischer at googlemail.com
Thu Feb 3 23:25:08 CET 2011
On Thursday 03 February 2011 23:03:36, Luke Palmer wrote:
> This is probably a result of strictness analysis. error is
> technically strict, so it is reasonable to optimize to:
> let e = error "foo" in e `seq` error e
I think so too.
module Errors where
foo = error (error "foo")
bar = error $ error "bar"
produces the core
Errors.bar :: forall a_aaN. a_aaN
\ (@ a_aaN) ->
(GHC.Err.error @ a_aaN)
(GHC.Err.error @ [GHC.Types.Char] (GHC.Base.unpackCString# "bar"))
a_rb8 :: [GHC.Types.Char]
[GblId, Str=DmdType b]
GHC.Err.error @ [GHC.Types.Char] (GHC.Base.unpackCString# "foo")
Errors.foo :: forall a_aaP. a_aaP
(\ (@ a_aaP) -> a_rb8)
`cast` (forall a_aaP. CoUnsafe [GHC.Types.Char] a_aaP
:: (forall a_aaP. [GHC.Types.Char]) ~ (forall a_aaP. a_aaP))
The first argument to ($) is evaluated before the second [because the
function may be lazy), resulting in the start of the error message
"***Exception: ", then that error-call must evaluate its argument, error
"bar", which results in "***Exception: bar" (and terminates the thread) and
two "***Exception: " being printed. If I interpret the core correctly,
error is so well known to the compiler that it strips off the outer `error'
in foo even without optimisations (which surprises me a bit).
With optimisations, ($) is inlined and `error $ error "bar"' is transformed
to error (error "bar"), from then on both have identical structure and
arrive at (mutatis mutandis) the same core (which is nearly the same as foo
got without optimisations).
More information about the Haskell-Cafe