[Haskell-cafe] Use unsafePerformIO to catch Exception?

Xiao-Yong Jin xj2106 at columbia.edu
Wed Mar 25 07:39:31 EDT 2009


Jonathan Cast <jonathanccast at fastmail.fm> writes:

> On Tue, 2009-03-24 at 23:13 -0700, Donn Cave wrote:
>> Quoth Duncan Coutts <duncan.coutts at worc.ox.ac.uk>:
>> 
>> > You must not do this. It breaks the semantics of the language.
>> >
>> > Other people have given practical reasons why you should not but a
>> > theoretical reason is that you've defined a non-continuous function.
>> > That is impossible in the normal semantics of pure functional languages.
>> > So you're breaking a promise which we rely on.
>> 
>> Could you elaborate a little, in what sense are we (?) relying on it?
>> 
>> I actually can't find any responses that make a case against it on a
>> really practical level - I mean, it seems to be taken for granted that
>> it will work as intended,
>
> It shouldn't be.
>
> Consider:
>
>     loop = loop
>     blam = error "blam"
>     notReallyTry = unsafePerformIO . try . evaluate
>
> Now, normally, we have, for all x, y,
>
>       x `seq` y `seq` x
>     = y `seq` x
>
> But we clearly do *not* have this for x = blam, y = loop, since the
> equality isn't preserved by notReallyTry:
>
>     notReallyTry $ blam `seq` loop `seq` blam = Left (ErrorCall "blam")
>     notReallyTry $ loop `seq` blam            = loop
>
> Now, say a compiler sees the definition
>
>     foo x y = x `seq` y `seq` x
>
> in one module, and then in a later one
>
>     expectToBeTotal = notReallyTry $ foo blam loop
>
> ?  What happens if the compiler, while compiling foo, notices that x is
> going to be evaluated eventually anyway, and decides against forcing it
> before y?
>
> What if foo was written as
>
>     foo (!x) (!y) = x
>
> ?  Which order are the evaluations performed in?  In a purely functional
> language, it doesn't matter; but all of a sudden with impure operations
> like notReallyTry popping up, it does.

Could you elaborate more about why this kind of breakage
wouldn't happen if 'try' is used in an IO monad as intended?

Thanks.
-- 
    c/*    __o/*
    <\     * (__
    */\      <


More information about the Haskell-Cafe mailing list