[Haskell-cafe] Re: Use unsafePerformIO to catch Exception?

ChrisK haskell at list.mightyreason.com
Mon Mar 23 08:41:19 EDT 2009


You should ensure that the result of "evaluate" is in normal form, not just weak 
head normal form.  You can do this with the Control.Parallel.Strategies module:

> import Control.Exception(ArithException(..),try,evaluate)
> import Control.Parallel.Strategies(NFData,using,rnf)
> import System.IO.Unsafe(unsafePerformIO)
> 
> tryArith :: NFData a => a -> Either ArithException a
> tryArith = unsafePerformIO . try . evaluate . flip using rnf
> 
> test :: [Either ArithException Integer]
> test =  map (tryArith . (div 5)) [2,1,0,5]
> 
> testResult = [Right 2,Right 5,Left DivideByZero,Right 1]
> 
> withPair :: Integer -> (Integer,Integer)
> withPair x = (x,throw Overflow)
> 
> main = do
>   print (test == testResult)
>   print (tryArith (withPair 7))
>    print (tryArith' (withPair 7))

in ghci

> *Main> main
> main
> True
> Left arithmetic overflow
> Right (7,*** Exception: arithmetic overflow


This "rnf :: Strategy a" ensures that the result of evaluate is in normal form. 
  This means it should not have any embedded lazy thunks, so any errors from 
such thunks will be forced while in the scope of the "try".

Otherwise a complex type like the result of withPair can hide an error.


Xiao-Yong Jin wrote:
> Hi,
> 
> I just feel it is not comfortable to deal with exceptions
> only within IO monad, so I defined
> 
>> tryArith :: a -> Either ArithException a
>> tryArith = unsafePerformIO . try . evaluate
> 
> and it works quite good as
> 
>> map (tryArith . (div 5)) [2,1,0,5]
> 
> evaluates to
> 
>> [Right 2,Right 5,Left divide by zero,Right 1]
> 
> However, I guess unsafePerformIO definitely has a reason for
> its name.  As I read through the document in
> System.IO.Unsafe, I can't convince myself whether the use of
> 'tryArith' is indeed safe or unsafe.
> 
> I know there have been a lot of discussion around
> unsafePerformIO, but I still can't figure it out by myself.
> Can someone share some thoughts on this particular use of
> unsafePerformIO?  Is it safe or not?  And why?
> 
> Thanks,
> Xiao-Yong



More information about the Haskell-Cafe mailing list