{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE ViewPatterns #-} import Control.Exception import System.IO.Unsafe whnfEither :: Exception e => a -> Either e a whnfEither x = unsafePerformIO $ try (evaluate x) pattern IsException :: Exception e => e -> a pattern IsException e <- (whnfEither -> Left e) where IsException e = throw e pattern MkSomeException e = IsException (e :: SomeException) pattern MkArithException e = IsException (e :: ArithException) pattern Pure :: a -> a pattern Pure x <- (whnfEither @SomeException -> Right x) foo :: a -> String foo (MkArithException e) = "ArithException: " ++ show e foo (MkSomeException e) = show e foo (Pure x) = "No exception thrown"