{-# LANGUAGE PatternGuards #-} -- | Generic utilities. module Proof.Util(module Proof.Util) where import System.IO.Unsafe import System.Environment import Control.DeepSeq rnf2 a b = rnf a `seq` rnf b rnf3 a b c = rnf a `seq` rnf b `seq` rnf c rnf4 a b c d = rnf a `seq` rnf b `seq` rnf c `seq` rnf d rnf5 a b c d e = rnf a `seq` rnf b `seq` rnf c `seq` rnf d `seq` rnf e headNote note (x:xs) = x headNote note [] = error $ "headNote on [], " ++ note fast = "--fast" `elem` unsafePerformIO getArgs idempotent :: (Show a, Eq a) => String -> (a -> a) -> (a -> a) idempotent name f x0 | fast = x1 | x1 == x2 = x1 | otherwise = error $ unlines ["START Idempotent check failed for " ++ name ++ "!" ,"Input:" ,show x0 ,"After first application:" ,show x1 ,"After second application:" ,show x2 ,"END Idempotent check failed for " ++ name ++ "!" ] where x1 = f x0 x2 = f x1 equivalentOn :: (Show a, Show b, Eq b) => (a -> b) -> String -> a -> a -> a equivalentOn op name x y | fast = y | xx == yy = y | otherwise = unsafePerformIO $ do writeFile "error.log" $ "-- Equivalent check failed for " ++ name ++ "\n" ++ show x error $ unlines ["START Equivalent check failed for " ++ name ++ "!" ,"Input:" ,show x ,"Output:" ,show y ,"Input (reduced):" ,show xx ,"Output (reduced):" ,show yy ,"END Equivalent check failed for " ++ name ++ "!" ] where xx = op x yy = op y simpleReadsPrec :: (String -> a) -> (Int -> ReadS a) simpleReadsPrec f _ s = [(f s, "")]