{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-} -- | Expression for 'Maybe'. module Language.Symantic.Expr.Maybe where import Control.Monad import qualified Data.Maybe as Maybe import qualified Data.Function as Fun import Data.Proxy (Proxy(..)) import Data.Type.Equality ((:~:)(Refl)) import Prelude hiding (maybe) import Language.Symantic.Type import Language.Symantic.Repr import Language.Symantic.Expr.Root import Language.Symantic.Expr.Error import Language.Symantic.Expr.From import Language.Symantic.Expr.Lambda import Language.Symantic.Trans.Common -- * Class 'Sym_Maybe_Lam' -- | Symantic. class Sym_Maybe repr where nothing :: repr (Maybe a) just :: repr a -> repr (Maybe a) maybe :: repr b -> repr ((->) a b) -> repr (Maybe a) -> repr b default nothing :: Trans t repr => t repr (Maybe a) default just :: Trans t repr => t repr a -> t repr (Maybe a) default maybe :: Trans t repr => t repr b -> t repr ((->) a b) -> t repr (Maybe a) -> t repr b nothing = trans_lift nothing just = trans_map1 just maybe = trans_map3 maybe instance Sym_Maybe Repr_Host where nothing = Repr_Host Nothing just = liftM Just maybe = liftM3 Maybe.maybe instance Sym_Maybe Repr_Text where nothing = Repr_Text $ \_p _v -> "nothing" just = repr_text_app1 "just" maybe = repr_text_app3 "maybe" instance ( Sym_Maybe r1 , Sym_Maybe r2 ) => Sym_Maybe (Dup r1 r2) where nothing = nothing `Dup` nothing just (a1 `Dup` a2) = just a1 `Dup` just a2 maybe (m1 `Dup` m2) (n1 `Dup` n2) (j1 `Dup` j2) = maybe m1 n1 j1 `Dup` maybe m2 n2 j2 -- * Type 'Expr_Maybe' -- | Expression. data Expr_Maybe (root:: *) type instance Root_of_Expr (Expr_Maybe root) = root type instance Type_of_Expr (Expr_Maybe root) = Type_Maybe type instance Sym_of_Expr (Expr_Maybe root) repr = (Sym_Maybe repr) type instance Error_of_Expr ast (Expr_Maybe root) = No_Error_Expr -- | Parsing utility to check that the given type is a 'Type_Maybe' -- or raise 'Error_Expr_Type_mismatch'. check_type_maybe :: forall ast ex root ty h ret. ( root ~ Root_of_Expr ex , ty ~ Type_Root_of_Expr ex , Type0_Lift Type_Maybe (Type_of_Expr root) , Type0_Unlift Type_Maybe (Type_of_Expr root) , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) ) => Proxy ex -> ast -> ty h -> (Type_Maybe ty h -> Either (Error_of_Expr ast root) ret) -> Either (Error_of_Expr ast root) ret check_type_maybe ex ast ty k = case type0_unlift $ unType_Root ty of Just ty_l -> k ty_l Nothing -> Left $ error_expr ex $ Error_Expr_Type_mismatch ast (Exists_Type0 (type_maybe $ type_var0 SZero :: ty (Maybe Var0))) (Exists_Type0 ty) -- | Parse 'maybe'. maybe_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_Maybe root) , Type0_Eq ty , Expr_From ast root , Type0_Lift Type_Fun (Type_of_Expr root) , Type0_Unlift Type_Fun (Type_of_Expr root) , Type0_Lift Type_Maybe (Type_of_Expr root) , Type0_Unlift Type_Maybe (Type_of_Expr root) , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) , Root_of_Expr root ~ root ) => ast -> ast -> ast -> ExprFrom ast (Expr_Maybe root) hs ret maybe_from ast_n ast_j ast_m ex ast ctx k = expr_from (Proxy::Proxy root) ast_n ctx $ \(ty_n::ty h_n) (Forall_Repr_with_Context n) -> expr_from (Proxy::Proxy root) ast_j ctx $ \(ty_j::ty h_j) (Forall_Repr_with_Context j) -> expr_from (Proxy::Proxy root) ast_m ctx $ \(ty_m::ty h_m) (Forall_Repr_with_Context m) -> check_type_fun ex ast ty_j $ \(Type2 Proxy ty_j_a ty_j_b :: Type_Fun ty h_j) -> check_type_maybe ex ast ty_m $ \(Type1 _ ty_m_a) -> check_type0_eq ex ast ty_n ty_j_b $ \Refl -> check_type0_eq ex ast ty_m_a ty_j_a $ \Refl -> k ty_n $ Forall_Repr_with_Context $ \c -> maybe (n c) (j c) (m c) -- | Parse 'nothing'. nothing_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_Maybe root) , Type0_From ast ty , Type0_Lift Type_Maybe (Type_of_Expr root) , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast) (Error_of_Expr ast root) , Root_of_Expr root ~ root ) => ast -> ExprFrom ast (Expr_Maybe root) hs ret nothing_from ast_ty_a ex ast _ctx k = case type0_from (Proxy::Proxy ty) ast_ty_a (Right . Exists_Type0) of Left err -> Left $ error_expr ex $ Error_Expr_Type err ast Right (Exists_Type0 ty_a) -> k (type_maybe ty_a) $ Forall_Repr_with_Context $ Fun.const nothing -- | Parse 'just'. just_from :: forall root ty ast hs ret. ( ty ~ Type_Root_of_Expr (Expr_Maybe root) , Expr_From ast root , Type0_Lift Type_Maybe (Type_of_Expr root) , Root_of_Expr root ~ root ) => ast -> ExprFrom ast (Expr_Maybe root) hs ret just_from ast_a _ex _ast ctx k = expr_from (Proxy::Proxy root) ast_a ctx $ \(ty_a::ty h_a) (Forall_Repr_with_Context a) -> k (type_maybe ty_a) $ Forall_Repr_with_Context $ \c -> just (a c)