{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} -- | Expression for @if@. module Language.Symantic.Expr.If where import Data.Proxy (Proxy(..)) import Data.Type.Equality ((:~:)(Refl)) import Language.Symantic.Expr.Common import Language.Symantic.Repr.Dup import Language.Symantic.Trans.Common import Language.Symantic.Type -- * Class 'Sym_If' -- | Symantic. class Sym_If repr where if_ :: repr Bool -> repr a -> repr a -> repr a default if_ :: Trans t repr => t repr Bool -> t repr a -> t repr a -> t repr a if_ = trans_map3 if_ instance -- Sym_If Dup ( Sym_If r1 , Sym_If r2 ) => Sym_If (Dup r1 r2) where if_ (c1 `Dup` c2) (ok1 `Dup` ok2) (ko1 `Dup` ko2) = if_ c1 ok1 ko1 `Dup` if_ c2 ok2 ko2 -- * Class 'Sym_When' -- | Symantic. class Sym_When repr where when :: repr Bool -> repr () -> repr () default when :: Trans t repr => t repr Bool -> t repr () -> t repr () when = trans_map2 when instance -- Sym_When Dup ( Sym_When r1 , Sym_When r2 ) => Sym_When (Dup r1 r2) where when (c1 `Dup` c2) (ok1 `Dup` ok2) = when c1 ok1 `Dup` when c2 ok2 -- * Type 'Expr_If' -- | Expression. data Expr_If (root:: *) type instance Root_of_Expr (Expr_If root) = root type instance Type_of_Expr (Expr_If root) = No_Type type instance Sym_of_Expr (Expr_If root) repr = (Sym_If repr) type instance Error_of_Expr ast (Expr_If root) = No_Error_Expr if_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_If root) , Eq_Type ty , Lift_Type_Root Type_Bool (Type_Root_of_Expr root) , Expr_from ast root , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) , Root_of_Expr root ~ root ) => ast -> ast -> ast -> Expr_From ast (Expr_If root) hs ret if_from ast_cond ast_ok ast_ko ex ast ctx k = expr_from (Proxy::Proxy root) ast_cond ctx $ \(ty_cond::Type_Root_of_Expr root h_n) (Forall_Repr_with_Context cond) -> expr_from (Proxy::Proxy root) ast_ok ctx $ \(ty_ok::Type_Root_of_Expr root h_ok) (Forall_Repr_with_Context ok) -> expr_from (Proxy::Proxy root) ast_ko ctx $ \(ty_ko::Type_Root_of_Expr root h_ko) (Forall_Repr_with_Context ko) -> check_eq_type ex ast type_bool ty_cond $ \Refl -> check_eq_type ex ast ty_ok ty_ko $ \Refl -> k ty_ok $ Forall_Repr_with_Context $ \c -> if_ (cond c) (ok c) (ko c) -- * Type 'Expr_When' -- | Expression. data Expr_When (root:: *) type instance Root_of_Expr (Expr_When root) = root type instance Type_of_Expr (Expr_When root) = No_Type type instance Sym_of_Expr (Expr_When root) repr = (Sym_When repr) type instance Error_of_Expr ast (Expr_When root) = No_Error_Expr when_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_When root) , Eq_Type ty , Lift_Type_Root Type_Bool (Type_Root_of_Expr root) , Lift_Type_Root Type_Unit (Type_Root_of_Expr root) , Expr_from ast root , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) , Root_of_Expr root ~ root ) => ast -> ast -> Expr_From ast (Expr_When root) hs ret when_from ast_cond ast_ok ex ast ctx k = expr_from (Proxy::Proxy root) ast_cond ctx $ \(ty_cond::Type_Root_of_Expr root h_n) (Forall_Repr_with_Context cond) -> expr_from (Proxy::Proxy root) ast_ok ctx $ \(ty_ok::Type_Root_of_Expr root h_ok) (Forall_Repr_with_Context ok) -> check_eq_type ex ast type_bool ty_cond $ \Refl -> check_eq_type ex ast type_unit ty_ok $ \Refl -> k ty_ok $ Forall_Repr_with_Context $ \c -> when (cond c) (ok c)