{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | Expression for 'Ord'. module Language.Symantic.Expr.Ord where import Data.Proxy (Proxy(..)) import Data.Type.Equality ((:~:)(Refl)) import Prelude hiding (compare) import Language.Symantic.Repr.Dup import Language.Symantic.Trans.Common import Language.Symantic.Type import Language.Symantic.Expr.Common import Language.Symantic.Expr.Lambda import Language.Symantic.Expr.Bool import Language.Symantic.Expr.Eq -- * Class 'Sym_Ord' -- | Symantic. class Sym_Eq repr => Sym_Ord repr where compare :: Ord a => repr a -> repr a -> repr Ordering default compare :: (Trans t repr, Ord a) => t repr a -> t repr a -> t repr Ordering compare = trans_map2 compare instance (Sym_Ord r1, Sym_Ord r2) => Sym_Ord (Dup r1 r2) where compare (x1 `Dup` x2) (y1 `Dup` y2) = compare x1 y1 `Dup` compare x2 y2 -- * Type 'Expr_Ord' -- | Expression. data Expr_Ord (root:: *) type instance Root_of_Expr (Expr_Ord root) = root type instance Type_of_Expr (Expr_Ord root) = No_Type type instance Sym_of_Expr (Expr_Ord root) repr = (Sym_Ord repr) type instance Error_of_Expr ast (Expr_Ord root) = No_Error_Expr ord_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_Ord root) , Type_Root_Lift Type_Bool (Type_Root_of_Expr root) , Type_Root_Lift Type_Ordering (Type_Root_of_Expr root) , Type_Eq (Type_Root_of_Expr root) , Expr_from ast root , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) , Root_of_Expr root ~ root , Type_Constraint Ord ty ) => ast -> ast -> Expr_From ast (Expr_Ord root) hs ret ord_from ast_x ast_y ex ast ctx k = expr_from (Proxy::Proxy root) ast_x ctx $ \(ty_x::Type_Root_of_Expr root h_x) (Forall_Repr_with_Context x) -> expr_from (Proxy::Proxy root) ast_y ctx $ \(ty_y::Type_Root_of_Expr root h_y) (Forall_Repr_with_Context y) -> when_type_eq ex ast ty_x ty_y $ \Refl -> when_type_constraint ex (Proxy::Proxy Ord) ast ty_x $ \Dict -> k type_ordering $ Forall_Repr_with_Context $ \c -> x c `compare` y c -- ** Type 'Expr_Lambda_Bool_Ord' -- | Convenient alias. type Expr_Lambda_Bool_Ord lam = Expr_Root (Expr_Alt (Expr_Lambda lam) (Expr_Alt Expr_Bool Expr_Ord)) -- | Convenient alias around 'expr_from'. expr_lambda_bool_ord_from :: forall lam ast. Expr_from ast (Expr_Lambda_Bool_Ord lam) => Proxy lam -> ast -> Either (Error_of_Expr ast (Expr_Lambda_Bool_Ord lam)) (Exists_Type_and_Repr (Type_Root_of_Expr (Expr_Lambda_Bool_Ord lam)) (Forall_Repr (Expr_Lambda_Bool_Ord lam))) expr_lambda_bool_ord_from _lam ast = expr_from (Proxy::Proxy (Expr_Lambda_Bool_Ord lam)) ast Context_Empty $ \ty (Forall_Repr_with_Context repr) -> Right $ Exists_Type_and_Repr ty $ Forall_Repr $ repr Context_Empty