Make stack flags customizable in GNUmakefile.
[haskell/symantic.git] / symantic-lib / Language / Symantic / Lib / Monad.hs
index dd8e85e76807aebb74fc25f305a0763ab75158ea..be0a36b98b01fc13602ee6f2279ec6310ac4e9b0 100644 (file)
+{-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 -- | Symantic for 'Monad'.
 module Language.Symantic.Lib.Monad where
 
 import Control.Monad (Monad)
-import qualified Control.Monad as Monad
-import Data.Proxy
-import Data.Type.Equality ((:~:)(Refl))
 import Prelude hiding (Monad(..))
+import qualified Control.Monad as Monad
 
-import Language.Symantic.Parsing
-import Language.Symantic.Typing
-import Language.Symantic.Compiling
-import Language.Symantic.Interpreting
-import Language.Symantic.Transforming
-import Language.Symantic.Lib.Applicative (Sym_Applicative)
+import Language.Symantic
+import Language.Symantic.Lib.Function (a0, b1, c2)
+import Language.Symantic.Lib.Unit (tyUnit)
+import Language.Symantic.Lib.Bool (tyBool)
 
 -- * Class 'Sym_Monad'
-class Sym_Applicative term => Sym_Monad term where
-       return :: Monad m => term a -> term (m a)
-       (>>=)  :: Monad m => term (m a) -> term (a -> m b) -> term (m b); infixl 1 >>=
-       join   :: Monad m => term (m (m a)) -> term (m a)
+type instance Sym Monad = Sym_Monad
+class Sym_Monad term where
+       return :: Monad m       => term a -> term (m a)
+       (>>=)  :: Monad m       => term (m a) -> term (a -> m b) -> term (m b); infixl 1 >>=
+       join   :: Monad m       => term (m (m a)) -> term (m a)
        when   :: Applicative f => term Bool -> term (f ()) -> term (f ())
+       (>=>)  :: Monad m       => term (a -> m b) -> term (b -> m c) -> term (a -> m c); infixr 1 >=>
        
-       default return :: (Trans t term, Monad m)
-        => t term a -> t term (m a)
-       default (>>=) :: (Trans t term, Monad m)
-        => t term (m a) -> t term (a -> m b) -> t term (m b)
-       default join :: (Trans t term, Monad m)
-        => t term (m (m a)) -> t term (m a)
-       default when :: (Trans t term, Applicative f)
-        => t term Bool -> t term (f ()) -> t term (f ())
+       default return :: Sym_Monad (UnT term) => Trans term => Monad m       => term a -> term (m a)
+       default (>>=)  :: Sym_Monad (UnT term) => Trans term => Monad m       => term (m a) -> term (a -> m b) -> term (m b)
+       default join   :: Sym_Monad (UnT term) => Trans term => Monad m       => term (m (m a)) -> term (m a)
+       default when   :: Sym_Monad (UnT term) => Trans term => Applicative f => term Bool -> term (f ()) -> term (f ())
+       default (>=>)  :: Sym_Monad (UnT term) => Trans term => Monad m       => term (a -> m b) -> term (b -> m c) -> term (a -> m c)
        
-       return = trans_map1 return
-       (>>=)  = trans_map2 (>>=)
-       join   = trans_map1 join
-       when   = trans_map2 when
-
-type instance Sym_of_Iface (Proxy Monad) = Sym_Monad
-type instance TyConsts_of_Iface (Proxy Monad) = Proxy Monad ': TyConsts_imported_by Monad
-type instance TyConsts_imported_by Monad =
- [ Proxy ()
- , Proxy Applicative
- , Proxy Bool
- ]
-
-instance Sym_Monad HostI where
-       return = Monad.liftM  Monad.return
-       (>>=)  = Monad.liftM2 (Monad.>>=)
-       join   = Monad.liftM  Monad.join
-       when   = Monad.liftM2 Monad.when
-instance Sym_Monad TextI where
-       return = textI1 "return"
-       (>>=)  = textI_infix ">>=" (infixL 1)
-       join   = textI1 "join"
-       when   = textI2 "when"
-instance (Sym_Monad r1, Sym_Monad r2) => Sym_Monad (DupI r1 r2) where
-       return = dupI1 @Sym_Monad return
-       (>>=)  = dupI2 @Sym_Monad (>>=)
-       join   = dupI1 @Sym_Monad join
-       when   = dupI2 @Sym_Monad when
-
-instance
- ( Read_TyNameR TyName cs rs
- , Inj_TyConst cs Monad
- ) => Read_TyNameR TyName cs (Proxy Monad ': rs) where
-       read_TyNameR _cs (TyName "Monad") k = k (ty @Monad)
-       read_TyNameR _rs raw k = read_TyNameR (Proxy @rs) raw k
-instance Show_TyConst cs => Show_TyConst (Proxy Monad ': cs) where
-       show_TyConst TyConstZ{} = "Monad"
-       show_TyConst (TyConstS c) = show_TyConst c
-
-instance Proj_TyConC cs (Proxy Monad)
-data instance TokenT meta (ts::[*]) (Proxy Monad)
- = Token_Term_Monad_return (EToken meta '[Proxy Token_Type]) (EToken meta ts)
- | Token_Term_Monad_bind   (EToken meta ts) (EToken meta ts)
- | Token_Term_Monad_join   (EToken meta ts)
- | Token_Term_Monad_when   (EToken meta ts) (EToken meta ts)
-deriving instance (Eq meta, Eq_Token meta ts) => Eq (TokenT meta ts (Proxy Monad))
-deriving instance (Show meta, Show_Token meta ts) => Show (TokenT meta ts (Proxy Monad))
-instance -- CompileI
- ( Read_TyName TyName cs
- , Inj_TyConst        cs Monad
- , Inj_TyConst        cs (->)
- , Inj_TyConst        cs ()
- , Inj_TyConst        cs Applicative
- , Inj_TyConst        cs Bool
- , Proj_TyCon         cs
- , Compile cs is
- ) => CompileI cs is (Proxy Monad) where
-       compileI tok ctx k =
-               case tok of
-                Token_Term_Monad_return tok_ty_m tok_a ->
-                       -- return :: Monad m => a -> m a
-                       compile_Type tok_ty_m $ \(ty_m::Type cs m) ->
-                       check_Kind
-                        (At Nothing (SKiType `SKiArrow` SKiType))
-                        (At (Just tok_ty_m) $ kind_of ty_m) $ \Refl ->
-                       check_TyCon (At (Just tok_ty_m) (ty @Monad :$ ty_m)) $ \TyCon ->
-                       compileO tok_a ctx $ \ty_a (TermO a) ->
-                       k (ty_m :$ ty_a) $ TermO $
-                        \c -> return (a c)
-                Token_Term_Monad_bind tok_ma tok_a2mb ->
-                       -- (>>=) :: Monad m => m a -> (a -> m b) -> m b
-                       compileO tok_ma   ctx $ \ty_ma   (TermO ma) ->
-                       compileO tok_a2mb ctx $ \ty_a2mb (TermO a2mb) ->
-                       check_TyCon1 (ty @Monad) (At (Just tok_ma) ty_ma) $ \Refl TyCon ty_ma_m ty_ma_a ->
-                       check_TyEq2 (ty @(->)) (At (Just tok_a2mb) ty_a2mb) $ \Refl ty_a2mb_a ty_a2mb_mb ->
-                       check_TyEq1 ty_ma_m (At (Just tok_a2mb) ty_a2mb_mb) $ \Refl _ty_a2mb_mb_b ->
-                       check_TyEq
-                        (At (Just tok_a2mb) ty_a2mb_a)
-                        (At (Just tok_ma) ty_ma_a) $ \Refl ->
-                       k ty_a2mb_mb $ TermO $
-                        \c -> (>>=) (ma c) (a2mb c)
-                Token_Term_Monad_join tok_mma ->
-                       -- join :: Monad m => m (m a) -> m a
-                       compileO tok_mma ctx $ \ty_mma (TermO mma) ->
-                       check_TyCon1 (ty @Monad) (At (Just tok_mma) ty_mma) $ \Refl TyCon ty_mma_m ty_mma_ma ->
-                       check_TyEq1 ty_mma_m (At (Just tok_mma) ty_mma_ma) $ \Refl _ty_mma_ma_a ->
-                       k ty_mma_ma $ TermO $
-                        \c -> join (mma c)
-                Token_Term_Monad_when tok_cond tok_ok ->
-                       -- when :: Applicative f => Bool -> f () -> f ()
-                       compileO tok_cond ctx $ \ty_cond (TermO cond) ->
-                       compileO tok_ok   ctx $ \ty_ok   (TermO ok) ->
-                       check_TyCon1 (ty @Applicative) (At (Just tok_ok) ty_ok) $ \Refl TyCon _ty_ok_f ty_ok_u ->
-                       check_TyEq
-                        (At Nothing (ty @Bool))
-                        (At (Just tok_cond) ty_cond) $ \Refl ->
-                       check_TyEq
-                        (At Nothing (ty @()))
-                        (At (Just tok_ok) ty_ok_u) $ \Refl ->
-                       k ty_ok $ TermO $
-                        \c -> when (cond c) (ok c)
-instance -- TokenizeT
- Inj_Token meta ts Monad =>
- TokenizeT meta ts (Proxy Monad) where
-       tokenizeT _t = mempty
-        { tokenizers_infix = tokenizeTMod []
-                [ (Term_Name "Nothing",) Term_ProTok
-                        { term_protok = \meta -> ProTokPi $ \m -> ProTokLam $ \a ->
-                               ProTok $ inj_EToken meta $ Token_Term_Monad_return m a
-                        , term_fixity = infixN5
-                        }
-                , tokenize2 ">>="  (infixL 1) Token_Term_Monad_bind
-                , tokenize1 "join" infixN5    Token_Term_Monad_join
-                , tokenize2 "when" infixN5    Token_Term_Monad_when
-                ]
-        }
-instance Gram_Term_AtomsT meta ts (Proxy Monad) g
+       return = trans1 return
+       (>>=)  = trans2 (>>=)
+       join   = trans1 join
+       when   = trans2 when
+       (>=>)  = trans2 (>=>)
+
+-- Interpreting
+instance Sym_Monad Eval where
+       return = eval1 Monad.return
+       (>>=)  = eval2 (Monad.>>=)
+       join   = eval1 Monad.join
+       when   = eval2 Monad.when
+       (>=>)  = eval2 (Monad.>=>)
+instance Sym_Monad View where
+       return = view1 "return"
+       (>>=)  = viewInfix ">>=" (infixL 1)
+       join   = view1 "join"
+       when   = view2 "when"
+       (>=>)  = viewInfix ">=>" (infixR 1)
+instance (Sym_Monad r1, Sym_Monad r2) => Sym_Monad (Dup r1 r2) where
+       return = dup1 @Sym_Monad return
+       (>>=)  = dup2 @Sym_Monad (>>=)
+       join   = dup1 @Sym_Monad join
+       when   = dup2 @Sym_Monad when
+       (>=>)  = dup2 @Sym_Monad (>=>)
+
+-- Transforming
+instance (Sym_Monad term, Sym_Lambda term) => Sym_Monad (BetaT term)
+
+-- Typing
+instance NameTyOf Monad where
+       nameTyOf _c = ["Monad"] `Mod` "Monad"
+instance FixityOf Monad
+instance ClassInstancesFor Monad
+instance TypeInstancesFor Monad
+
+-- Compiling
+instance Gram_Term_AtomsFor src ss g Monad
+instance (Source src, SymInj ss Monad) => ModuleFor src ss Monad where
+       moduleFor = ["Monad"] `moduleWhere`
+        [ "return" := teMonad_return
+        , "join"   := teMonad_join
+        , "when"   := teMonad_when
+        , ">>=" `withInfixL` 1 := teMonad_bind
+        , ">=>" `withInfixR` 1 := teMonad_kleisli_l2r
+        ]
+
+-- ** 'Type's
+tyMonad :: Source src => Type src vs m -> Type src vs (Monad m)
+tyMonad m = tyConstLen @(K Monad) @Monad (lenVars m) `tyApp` m
+
+m0 :: Source src => LenInj vs => KindInj (K m) =>
+     Type src (Proxy m ': vs) m
+m0 = tyVar "m" varZ
+
+m1 :: Source src => LenInj vs => KindInj (K m) =>
+     Type src (a ': Proxy m ': vs) m
+m1 = tyVar "m" $ VarS varZ
+
+m2 :: Source src => LenInj vs => KindInj (K m) =>
+     Type src (a ': b ': Proxy m ': vs) m
+m2 = tyVar "m" $ VarS $ VarS varZ
+
+m3 :: Source src => LenInj vs => KindInj (K m) =>
+     Type src (a ': b ': c ': Proxy m ': vs) m
+m3 = tyVar "m" $ VarS $ VarS $ VarS varZ
+
+-- ** 'Term's
+teMonad_return :: TermDef Monad '[Proxy a, Proxy m] (Monad m #> (a -> m a))
+teMonad_return = Term (tyMonad m1) (a0 ~> m1 `tyApp` a0) $ teSym @Monad $ lam1 return
+
+teMonad_bind :: TermDef Monad '[Proxy a, Proxy b, Proxy m] (Monad m #> (m a -> (a -> m b) -> m b))
+teMonad_bind = Term (tyMonad m2) (m2 `tyApp` a0 ~> (a0 ~> m2 `tyApp` b1) ~> m2 `tyApp` b1) $ teSym @Monad $ lam2 (>>=)
+
+teMonad_join :: TermDef Monad '[Proxy a, Proxy m] (Monad m #> (m (m a) -> m a))
+teMonad_join = Term (tyMonad m1) (m1 `tyApp` (m1 `tyApp` a0) ~> m1 `tyApp` a0) $ teSym @Monad $ lam1 join
+
+teMonad_kleisli_l2r :: TermDef Monad '[Proxy a, Proxy b, Proxy c, Proxy m] (Monad m #> ((a -> m b) -> (b -> m c) -> (a -> m c)))
+teMonad_kleisli_l2r = Term (tyMonad m3) ((a0 ~> m3 `tyApp` b1) ~> (b1 ~> m3 `tyApp` c2) ~> (a0 ~> m3 `tyApp` c2)) $ teSym @Monad $ lam2 (>=>)
+
+teMonad_when :: TermDef Monad '[Proxy m] (Monad m #> (Bool -> m () -> m ()))
+teMonad_when = Term (tyMonad m0) (tyBool ~> m0 `tyApp` tyUnit ~> m0 `tyApp` tyUnit) $ teSym @Monad $ lam2 when