packages feed

hermit-0.1.4.0: examples/evaluation/Eval.hs

module Main where

import Data.Function(fix)

data Expr = Val Int | Add Expr Expr | Throw | Catch Expr Expr

type Mint = Maybe Int

eval :: Expr -> Mint
eval (Val n)     = Just n
eval Throw       = Nothing
eval (Catch x y) = case eval x of
                       Nothing -> eval y
                       Just n  -> Just n
eval (Add x y)   = case eval x of
                       Nothing -> Nothing
                       Just m  -> case eval y of
                                    Nothing -> Nothing
                                    Just n  -> Just (m + n)

unwrap :: (Expr -> Mint) -> Expr -> (Int -> Mint) -> Mint -> Mint
unwrap g e s f = case g e of
                   Nothing -> f
                   Just n  -> s n

wrap :: (Expr -> (Int -> Mint) -> Mint -> Mint) -> Expr -> Mint
wrap h e = h e Just Nothing

{-# RULES "ww"     forall f. fix f = wrap (fix (unwrap . f . wrap)) #-}
{-# RULES "fusion" forall w. unwrap (wrap w) = w                    #-} -- has precondition

main :: IO ()
main = print (eval $ Val 5)