{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RebindableSyntax #-} {-# OPTIONS_GHC -Wno-missing-signatures #-} {-# OPTIONS_GHC -Wno-unused-top-binds #-} -- Code from README.md module README where import qualified Prelude import Control.Applicative (liftA2) import Dino import Dino.AST (drawTree) import Dino.Interpretation -------------------------------------------------------------------------------- -- * Syntax -------------------------------------------------------------------------------- ex1 :: (ConstExp e, NumExp e, FracExp e, CompareExp e, CondExp e) => Exp e Double -> Exp e Text ex1 a = if a > 4.5 then "greater" else "smaller or equal" beaufortScale :: (ConstExp e, NumExp e, FracExp e, CompareExp e, CondExp e) => Exp e Double -> Exp e Text beaufortScale v = cases [ (v < 0.5) --> "calm" , (v < 13.8) --> "breeze" , (v < 24.5) --> "gale" ] ( Otherwise --> "storm" ) safeDiv :: (ConstExp e, FracExp e, CompareExp e, CondExp e, DinoType a, Fractional a) => e a -> e a -> Optional e (e a) safeDiv a b = suppose $ if (b /= lit 0) then just (fdiv a b) else nothing foo :: (ConstExp e, NumExp e, FracExp e, CompareExp e, CondExp e, LetExp e) => Exp e Double -> Exp e Double -> Exp e Double foo a b = fromOptional 0 $ do x <- safeDiv a b y <- safeDiv b x safeDiv x y -- Let's have look at the expression generated by `foo`: fooExp = drawTree $ unReified $ prodSnd $ unIntensional $ unExp $ foo 111 222 -- The type of `foo` here is `Exp (Intensional Reified) Double` -------------------------------------------------------------------------------- -- * Semantics -------------------------------------------------------------------------------- newtype SafeDiv a = SafeDiv {fromSafeDiv :: Maybe a} deriving (Functor, Applicative, Monad) instance ConstExp SafeDiv instance NumExp SafeDiv instance LogicExp SafeDiv instance CompareExp SafeDiv instance FracExp SafeDiv where fdiv _ (SafeDiv (Just b)) | b Prelude.== 0 = SafeDiv Nothing fdiv (SafeDiv a) (SafeDiv b) = SafeDiv (liftA2 (/) a b) evalSafeDiv :: (forall e. (ConstExp e, NumExp e, FracExp e, LogicExp e, CompareExp e) => Exp e a) -> Maybe a evalSafeDiv = fromSafeDiv . unExp ex2 :: (ConstExp e, NumExp e, FracExp e, LogicExp e, CompareExp e) => Exp e Double ex2 = 1+2/3 ex3 :: (ConstExp e, NumExp e, FracExp e, LogicExp e, CompareExp e) => Exp e Double ex3 = 1+2/0 -------------------------------------------------------------------------------- tests = do print $ eval $ ex1 2 print $ eval $ ex1 5 print $ eval $ beaufortScale 8 print $ eval $ foo 11 12 print $ eval $ foo 11 0 fooExp print $ evalSafeDiv ex2 print $ evalSafeDiv ex3