Working REPL, with IO support.
authorJulien Moutinho <julm+hcompta@autogeree.net>
Wed, 30 Aug 2017 12:49:16 +0000 (14:49 +0200)
committerJulien Moutinho <julm+hcompta@autogeree.net>
Wed, 30 Aug 2017 12:49:16 +0000 (14:49 +0200)
lcc/Hcompta/LCC/Balance.hs
lcc/Hcompta/LCC/Compta.hs
lcc/Hcompta/LCC/Sym.hs
lcc/Hcompta/LCC/Sym/Balance.hs
lcc/Hcompta/LCC/Sym/LCC.hs
lcc/exe/eval/Main.hs

index 450f5a2e7e9d39d8c680f38f1cefc45fbc3eb102..124a7494c082a8e88ee1fa51934193620104b169 100644 (file)
@@ -50,9 +50,7 @@ instance H.Sumable Balance a => H.Sumable Balance (Compta src ss a) where
 instance H.Sumable Balance (Map Date [Transaction src]) where
        bal += m = MT.ofoldr (flip (H.+=)) bal m
 
-{-
 -- * Class 'Balanceable'
 type Balanceable = H.Sumable Balance
 balance :: Balanceable a => a -> Balance
 balance = H.sum
--}
index 266a997cde08b2a9e265d3bd06dab34d470d71b4..16cb18d6020ab28489c560641ca470416dd718d8 100644 (file)
@@ -1,17 +1,18 @@
+{-# LANGUAGE ExistentialQuantification #-}
 module Hcompta.LCC.Compta where
 
-import Control.Applicative (Applicative(..))
 import Control.Monad (Monad(..))
 import Data.Bool (Bool(..))
 import Data.Either (either)
 import Data.Eq (Eq)
 import Data.Function (($), (.), id)
-import Data.Functor (Functor(..), (<$>))
-import Data.Typeable (Typeable)
+import Data.Functor ((<$>))
+import Data.Functor.Identity (Identity(..))
 import Prelude (error)
 import Text.Show (Show(..))
 import qualified Control.Monad.Classes as MC
 import qualified Control.Monad.Trans.State.Strict as SS
+import qualified Hcompta.LCC.Lib.Strict as S
 
 import Hcompta.LCC.Amount
 import Hcompta.LCC.Balance
@@ -21,7 +22,6 @@ import Hcompta.LCC.IO
 import Hcompta.LCC.Transaction
 import Language.Symantic as Sym
 import qualified Hcompta as H
-import qualified Hcompta.LCC.Lib.Strict as S
 
 -- * Type 'LCC'
 data LCC src
@@ -33,6 +33,8 @@ data LCC src
  } deriving (Eq, Show)
 instance H.Get Style_Amounts (LCC src) where
        get = lcc_style
+instance H.Sumable Balance (LCC src) where
+       b += l = b H.+= lcc_journals l
 
 -- ** Type 'State_Sym'
 data State_Sym src ss
@@ -72,21 +74,49 @@ instance Monad m => MC.MonadStateN 'MC.Zero (Sym.Imports Sym.NameTy, Sym.Modules
        stateN _px f = S.StateT $ SS.state $ \st ->
                (\a -> st{state_sym_types=a}) <$> f (state_sym_types st)
 
--- * Type 'Context'
-type Context m = SS.State m
+-- * Type 'Database'
+newtype Database db a = Database (S.StateT db Identity a)
+
+-- * Type 'Query'
+newtype Query db a = Query { runQuery :: db -> a }
+
+-- * Type 'Queryable'
+class Queryable db a where
+       query :: Query db a
+instance Queryable (LCC src) Balance where
+       query = Query $ H.sum . lcc_journals
+
+{-
+-- * Type 'Base'
+data Base =
+ forall db.
+ Typeable db =>
+ Base (Type src vs db) db
+
+-- * Type 'DataBase'
+data DataBase = forall db. Typeable db => DataBase db
 
 -- * Type 'Code'
 newtype Code src ss m a
  =      Code (S.StateT (State_Sym src (Sym.Proxy (Code src ss) ': ss)) m a)
  deriving (Functor, Applicative, Monad, Typeable)
+-}
 
+{-
 -- * Class 'Balanceable'
-class Balanceable ctx where
-       balance :: Context ctx Balance
+class Balanceable a where
+       balance :: a -> Balance
 instance Balanceable (LCC src) where
-       balance = do
-               js <- SS.gets lcc_journals
-               return (H.sum js)
+       balance = H.sum . lcc_journals @src
+-}
+
+-- LCC src
+type instance MC.CanDo (S.StateT (LCC src) m) (MC.EffState (LCC src)) = 'True
+instance Monad m => MC.MonadStateN 'MC.Zero (LCC src) (S.StateT (LCC src) m) where
+       stateN _px = S.StateT . SS.state
+
+
+
 
 
 {-
index 22b8d459c3353d198fd0c7f3b0353a74be6ea09b..a96e42de59a7827157bf07400ed1583004a7aa22 100644 (file)
@@ -6,7 +6,7 @@ module Hcompta.LCC.Sym
  , module Hcompta.LCC.Sym.Account
  , module Hcompta.LCC.Sym.Addable
  , module Hcompta.LCC.Sym.Amount
-- , module Hcompta.LCC.Sym.Balance
+ , module Hcompta.LCC.Sym.Balance
  , module Hcompta.LCC.Sym.Chart
  -- , module Hcompta.LCC.Sym.Code
  -- , module Hcompta.LCC.Sym.Compta
@@ -33,7 +33,7 @@ import qualified Language.Symantic.Lib as Sym
 import Hcompta.LCC.Sym.Account
 import Hcompta.LCC.Sym.Addable
 import Hcompta.LCC.Sym.Amount
--- import Hcompta.LCC.Sym.Balance
+import Hcompta.LCC.Sym.Balance
 import Hcompta.LCC.Sym.Chart
 -- import Hcompta.LCC.Sym.Compta
 -- import Hcompta.LCC.Sym.Code
@@ -54,7 +54,7 @@ import Hcompta.LCC.Sym.Zipper
 
 import qualified Hcompta.LCC.Account as LCC
 import qualified Hcompta.LCC.Amount as LCC
--- import qualified Hcompta.LCC.Balance as LCC
+import qualified Hcompta.LCC.Balance as LCC
 import qualified Hcompta.LCC.Chart as LCC
 import qualified Hcompta.LCC.Compta as LCC
 import qualified Hcompta.LCC.IO as LCC
@@ -94,6 +94,7 @@ type SRC = Sym.SrcTe LCC.SourcePath SS'
 type SS' =
  [ Proxy (->)
  , Proxy (,)
+ , Proxy ()
  , Proxy Alternative
  , Proxy Applicative
  , Proxy Bool
@@ -110,7 +111,7 @@ type SS' =
  , Proxy IsSequence
  , Proxy LCC.Account
  , Proxy LCC.Amounts
-- , Proxy LCC.Balance
+ , Proxy LCC.Balance
  , Proxy LCC.Chart
  , Proxy LCC.Date
  , Proxy (LCC.Journal LCC.SourceRead)
index 6d805372816ad74506b63a26c52f7761be07282f..c1828de41775808792fa9a4ce1706379f0ba3946 100644 (file)
@@ -3,7 +3,6 @@
 -- | Symantic for 'Balance'.
 module Hcompta.LCC.Sym.Balance where
 
-{-
 import Data.Maybe (Maybe(..))
 import Text.Show (Show(..))
 
@@ -34,6 +33,14 @@ instance NameTyOf Balance where
        nameTyOf _c = ["Balance"] `Mod` "Balance"
 -- instance FixityOf Balance
 instance ClassInstancesFor Balance where
+       {-
+       proveConstraintFor _ (TyConst _ _ c :$ q :@ db :@ b)
+        | Just HRefl <- proj_ConstKiTy @_ @RunQuery c
+        , Just HRefl <- proj_ConstKiTy @_ @Query q
+        , Just HRefl <- proj_ConstKiTy @_ @(LCC.LCC LCC.SourceRead) db
+        , Just HRefl <- proj_ConstKiTy @_ @Balance b
+        = Just Dict
+       -}
        proveConstraintFor _ (TyConst _ _ q :$ b)
         | Just HRefl <- proj_ConstKiTy @_ @Balance b
         = case () of
@@ -55,4 +62,3 @@ tyBalanceable a = tySumable (tyConstLen @(K Balance) @Balance (lenVars a)) a
 
 teBalance_balance :: TermDef Balance '[Proxy a] (Balanceable a #> (a -> Balance))
 teBalance_balance = Term (tyBalanceable a0) (a0 ~> tyBalance) (teSym @Balance (lam1 balance))
--}
index de00aab3c75a82ca4d32cc6eb7a4786451d26d28..3fe12424f2b731fa0a5dc831aa8559501dc21bad 100644 (file)
@@ -20,6 +20,8 @@ import Hcompta.LCC.Read ()
 import Hcompta.LCC.Sym.FileSystem (tyPathFile)
 import Hcompta.LCC.Sym.IO (fromFile, Sym_FromFile)
 import Hcompta.LCC.Write
+import Hcompta.LCC.Balance
+import qualified Hcompta as H
 
 import Language.Symantic
 import qualified Language.Symantic.Document as Doc
@@ -60,6 +62,11 @@ instance (Typeable sou, Eq sou, Show sou) => ClassInstancesFor (LCC sou) where
                           | Just HRefl <- proj_ConstKiTy @(K Doc.PlainIO) @Doc.PlainIO d -> Just Dict
                         _ -> Nothing
                 _ -> Nothing
+       proveConstraintFor _ (q:@b:@a)
+        | Just HRefl <- proj_ConstKiTy @(K H.Sumable) @H.Sumable q
+        , Just HRefl <- proj_ConstKiTy @(K Balance) @Balance b
+        , Just HRefl <- proj_ConstKiTy @(K (LCC sou)) @(LCC sou) a
+        = Just Dict
        proveConstraintFor _ (q:@a)
         | Just HRefl <- proj_ConstKiTy @(K (LCC sou)) @(LCC sou) a
         = case () of
index af45bb69f6e8bfc5ff447c807f7ce74b7c560a55..fa51a937d5a1601aae047485df5d07c57bf17f9e 100644 (file)
@@ -1,13 +1,15 @@
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE ViewPatterns #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE GADTs #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ViewPatterns #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Main where
 
+import Control.Arrow (left)
 import Control.Applicative (Applicative(..))
-import Control.Monad (Monad(..), void)
+import Control.Monad (Monad(..), void, when)
 import Control.Monad.IO.Class (MonadIO(..))
 import Control.Monad.Trans.Class as MT (MonadTrans(..))
 import Data.Bool (Bool(..))
@@ -17,14 +19,16 @@ import Data.Eq (Eq(..))
 import Data.Function (($), (.), id)
 import Data.Functor (Functor(..), (<$>))
 import Data.Maybe (Maybe(..), maybe)
+import Data.Monoid (Monoid(..))
 import Data.Semigroup ((<>))
 import Data.String (String)
 import Data.Text (Text)
-import Prelude (error, succ, Integer)
+import Prelude (error, succ, Integer, undefined)
 import System.Console.Haskeline as HL
 import System.IO (IO, putStr, putStrLn, print)
 import Text.Show (Show(..))
 import qualified Control.Monad.Classes as MC
+import qualified Control.Monad.Classes.Run as MC
 import qualified Control.Monad.Trans.State.Strict as SS
 import qualified Data.Char as Char
 import qualified Data.List as L
@@ -56,16 +60,18 @@ main = do
         { historyFile    = Just ".hcompta.history"
         , autoAddHistory = False
         } $
-               S.evalState (LCC.state_sym @LCC.Sym.SRC @LCC.Sym.SS) $
-               unREPL (loop True 0)
+               MC.evalStateStrict evalTeUnit $
+               S.evalState (LCC.state_sym @LCC.Sym.SRC @(Proxy Eval ': LCC.Sym.SS)) $
+               unREPL $ loop True 0
        where
        loop :: forall src ss.
         Show src =>
         Syms ss Eval =>
-        Syms ss View =>
-        Syms ss (BetaT View) =>
+        -- Syms ss View =>
+        -- Syms ss (BetaT View) =>
+        SymInj ss Eval =>
         ReadTe src ss =>
-        Gram_Term src ss (G src ss (InputT IO)) =>
+        Gram_Term src ss (G src ss (SS.StateT (TermVT src ss '[]) (InputT IO))) =>
         Bool -> Integer -> REPL src ss ()
        loop ok i = do
                let prompt =
@@ -79,7 +85,7 @@ main = do
                case line of
                 Nothing -> loop ok i
                 Just l -> do
-                       void $ REPL $ lift $
+                       void $ REPL $ lift $ lift $
                                HL.modifyHistory $
                                HL.addHistoryRemovingAllDupes l
                        REPL (parseTe $ Text.pack l) >>= \case
@@ -88,8 +94,9 @@ main = do
                                loop False (succ i)
                         Right expr ->
                                case expr of
-                                Command_Def nam ast -> runTe nam ast
-                                Command_Eval    ast -> runTe "it" ast
+                                Command_Def  nam ast -> runTe nam ast
+                                Command_Bind nam ast -> runTe nam ast
+                                Command_Eval     ast -> runTe "ans" ast
                where
                runTe nam ast =
                        case readTe ast of
@@ -100,30 +107,51 @@ main = do
                                REPL $ do
                                        MC.modify $ \(imps::Imports NameTe, mods) ->
                                                (imps, insTerm nam te mods)
-                                       evalTe te
+                                       lr_r <- evalTe te
+                                       case lr_r of
+                                        Right r ->
+                                               when (nam == NameTe "base") $ MC.put r
+                                        Left (Error_Eval_Cannot_prove_Constraint (TypeVT q)) ->
+                                               printTy q >>= ansiIO . ("Cannot prove Constraint: " <>)
                                loop True (succ i)
-               insTerm :: Sym.NameTe -> Sym.TermVT src ss '[] -> Sym.Modules src ss -> Sym.Modules src ss
-               insTerm n t = Sym.insertTermVT ([] `Sym.Mod` t) n (Sym.Fixity2 Sym.infixN5)
-
+               insTerm ::
+                Sym.NameTe ->
+                Sym.TermVT src ss '[] ->
+                Sym.Modules src ss ->
+                Sym.Modules src ss
+               insTerm n t =
+                       Sym.insertTermVT ([] `Sym.Mod` t) n $
+                       Sym.Fixity2 Sym.infixN5
+
+type instance MC.CanDo (S.StateT (LCC.State_Sym src ss) m) (MC.EffState (TermVT src ss '[])) = 'False
+-- type instance MC.CanDo (S.StateT (LCC.State_Sym src ss) m) (MC.EffState (EvalVT src)) = 'False
+
+-- * Type 'G'
 type G src ss m =
  P.ParsecT P.Dec Text
            (S.StateT (LCC.State_Sym src ss) m)
 
+-- * Type 'Command'
 data Command src ss
  =   Command_Eval (AST_Term src ss)
  |   Command_Def  NameTe (AST_Term src ss)
+ |   Command_Bind NameTe (AST_Term src ss)
  deriving (Eq, Show)
 
 parseTe ::
  forall ss src m.
  Monad m =>
  Gram_Term src ss (G src ss m) =>
- Text -> S.StateT (LCC.State_Sym src ss) m
-                  (Either (P.ParseError Char P.Dec) (Command src ss))
+ Text ->
+ S.StateT (LCC.State_Sym src ss) m
+          (Either (P.ParseError Char P.Dec) (Command src ss))
 parseTe = P.runParserT g ""
        where
        g :: G src ss m (Command src ss)
-       g = G.unCF $ G.try gCmdLet G.<+> gCmdEval
+       g = G.unCF $
+               G.try gCmdLet G.<+>
+               G.try gCmdBind G.<+>
+               gCmdEval
        gCmdLet =
                Command_Def
                 <$  G.optional (G.try $ G.symbol "let")
@@ -135,6 +163,12 @@ parseTe = P.runParserT g ""
                Command_Eval
                 <$> Sym.g_term
                 <*  G.eoi
+       gCmdBind =
+               Command_Bind
+                <$> Sym.g_NameTe
+                <*  G.symbol "<-"
+                <*> Sym.g_term
+                <*  G.eoi
 
 -- * Type 'ReadTe'
 type ReadTe src ss =
@@ -146,8 +180,8 @@ type ReadTe src ss =
 readTe ::
  forall src ss.
  ( Syms ss Eval
- , Syms ss View
- , Syms ss (BetaT View)
-- , Syms ss View
-- , Syms ss (BetaT View)
  , ReadTe src ss
  ) =>
  AST_Term src ss ->
@@ -158,28 +192,68 @@ readTe = Sym.readTerm CtxTyZ
 ansiIO :: MonadIO m => D.ANSI_IO -> m ()
 ansiIO = liftIO . (`D.ansiIO` IO.stdout)
 
+-- * Type 'Error_Eval'
+data Error_Eval src
+ =   Error_Eval_Cannot_prove_Constraint (TypeVT src)
+ deriving (Eq, Show)
+
 evalTe ::
  forall src ss m.
  Source src =>
- Syms ss View =>
  Syms ss Eval =>
- Syms ss (BetaT View) =>
+ -- Syms ss View =>
+ -- Syms ss (BetaT View) =>
+ SymInj ss Eval =>
+ SourceInj (TypeVT src) src =>
  MonadIO m =>
  TermVT src ss '[] ->
- S.StateT (LCC.State_Sym src ss) m ()
-evalTe (TermVT (Term q t (TeSym te))) = do
+ S.StateT (LCC.State_Sym src ss)
+          (SS.StateT (TermVT src ss '[]) m)
+          (Either (Error_Eval src) (TermVT src ss '[]))
+evalTe te@(TermVT (Term q t (TeSym sym))) = do
        printTy (q #> t) >>= ansiIO . ("Type: " <>)
-       case proveConstraint q of
-        Nothing -> printTy q >>= ansiIO . ("Cannot prove Constraint: " <>)
-        Just Dict -> liftIO $ do
-               Text.putStrLn $ "View: " <> view (betaT $ te CtxTeZ)
-               case t of
-                io:@aTy | Just HRefl <- proj_ConstKiTy @_ @IO io -> do
-                       a <- eval $ te CtxTeZ
-                       printTe aTy a
-                aTy ->
-                       let a = eval $ te CtxTeZ in
+       -- liftIO $ Text.putStrLn $ "View: " <> view (betaT $ sym CtxTeZ)
+       case t of
+        io:@aTy | Just HRefl <- proj_ConstKiTy @_ @IO io -> do
+               case proveConstraint q of
+                Nothing -> return $ Left $ Error_Eval_Cannot_prove_Constraint $ TypeVT q
+                Just Dict -> do
+                       a <- liftIO $ eval $ sym CtxTeZ
+                       let r = TermVT $ teEval_uneval aTy a
                        printTe aTy a
+                       return $ Right r
+        _ -> do
+               r@(TermVT (Term q' t' (TeSym sym'))) <- completeTe te
+               printTy (q' #> t') >>= ansiIO . ("Type: Completed: " <>)
+               case proveConstraint q' of
+                Nothing -> return $ Left $ Error_Eval_Cannot_prove_Constraint $ TypeVT q'
+                Just Dict -> do
+                       let a = eval $ sym' CtxTeZ
+                       printTe t' a
+                       return $ Right r
+
+completeTe ::
+ forall src ss m.
+ Source src =>
+ Syms ss Eval =>
+ -- Syms ss View =>
+ -- Syms ss (BetaT View) =>
+ SourceInj (TypeVT src) src =>
+ MonadIO m =>
+ TermVT src ss '[] ->
+ S.StateT (LCC.State_Sym src ss)
+          (SS.StateT (TermVT src ss '[]) m)
+          (TermVT src ss '[])
+completeTe t = do
+       liftIO $ putStrLn "completeTe"
+       st :: TermVT src ss '[] <- MC.get
+       case betaTerms $ G.BinTree0 t `G.BinTree2` G.BinTree0 st of
+        Left _  -> do
+               liftIO $ putStrLn "completeTe: Left"
+               return t
+        Right s -> do
+               liftIO $ putStrLn "completeTe: Right"
+               return s
 
 printTy ::
  forall src ss m vs t d.
@@ -197,22 +271,27 @@ printTy ty = do
                 , config_Doc_Type_imports        = impsTy
                 } 0 ty <> D.eol
 
-printTe :: Source src => Type src vs a -> a -> IO ()
+printTe :: Source src => MonadIO m => Type src vs a -> a -> m ()
 printTe aTy a =
        case proveConstraint $ LCC.Sym.tyWriteable
         (allocVarsR (lenVars aTy) $ LCC.Sym.tyContext_Write @_ @'[] ~> LCC.Sym.tyANSI_IO) aTy of
-        Just Dict -> (`D.ansiIO` IO.stdout) $ write a context_write
-        Nothing ->
+        Just Dict -> ansiIO $ write a context_write
+        Nothing -> liftIO $
                case proveConstraint $ Sym.tyShow aTy of
                 Nothing -> putStrLn $ "No Show instance for type: " <> show aTy
-                Just Dict -> print a
+                Just Dict -> do
+                       putStrLn "Show:"
+                       print a
 
 
 -- * Type 'REPL'
 -- /Read Eval Print Loop/ monad.
 newtype REPL src ss a
  =      REPL
- {    unREPL :: S.StateT (LCC.State_Sym src ss) (InputT IO) a }
+ {    unREPL :: S.StateT (LCC.State_Sym src ss)
+                         (SS.StateT (TermVT src ss '[])
+                                    (InputT IO))
+                         a }
  deriving ( Functor
           , Applicative
           , Monad
@@ -223,21 +302,36 @@ newtype REPL src ss a
 instance MonadTrans (REPL src ss) where
        lift = REPL . lift . lift
 -}
-type instance MC.CanDo (REPL src ss) (MC.EffState (LCC.State_Sym src ss)) = 'False
+type instance MC.CanDo (REPL src ss) (MC.EffState (LCC.State_Sym src ss))               = 'False
 type instance MC.CanDo (REPL src ss) (MC.EffState (Sym.Imports ns, Sym.Modules src ss)) = 'False
 type instance MC.CanDo (REPL src ss) (MC.EffState (Sym.Imports ns, Sym.ModulesTy src))  = 'False
+type instance MC.CanDo (REPL src ss) (MC.EffState (Sym.TermVT src ss '[]))              = 'False
+-- type instance MC.CanDo (REPL src ss) (MC.EffState (EvalVT src))                       = 'False
 
+{-
 -- * Type 'State_REPL'
-data State_REPL
+data State_REPL src ss
  =   State_REPL
- {   state_repl_env :: ()
+ {   state_repl_terms :: LCC.State_Sym src ss
+ ,   state_repl_db    :: db
  }
 
+-- State_REPL src ss db
+type instance MC.CanDo (S.StateT (State_REPL src ss db) m) (MC.EffState (State_REPL src ss db)) = 'True
+instance Monad m => MC.MonadStateN 'MC.Zero (State_REPL src ss db) (S.StateT (State_REPL src ss db) m) where
+       stateN _px = S.StateT . SS.state
+
+-- LCC.State_Sym src ss
+type instance MC.CanDo (S.StateT (State_REPL src ss db) m) (MC.EffState (State_REPL src ss db)) = 'True
+instance Monad m => MC.MonadStateN 'MC.Zero (State_REPL src ss db) (S.StateT (LCC.State_Sym src ss) m) where
+       stateN _px f = S.StateT $ SS.state $ \st ->
+               (\a -> st{state_repl_terms=a}) <$> f (state_repl_terms st)
+-}
 
 
 readLine :: String -> REPL src ss (Maybe String)
 readLine prompt = do
-       line <- REPL . lift $ getInputLine prompt
+       line <- REPL . lift . lift $ getInputLine prompt
        case line of
         Just l@(':':_) -> return $ Just l
         Just l@(_:_) | L.last l == ' ' -> readLines l
@@ -246,7 +340,7 @@ readLine prompt = do
        where
        readLines :: String -> REPL src ss (Maybe String)
        readLines acc = do
-               line <- REPL . lift $ getInputLine ""
+               line <- REPL . lift . lift $ getInputLine ""
                case line of
                 Just l@(_:_) | L.last l == ' ' -> readLines $ acc <> l
                 Just l  -> return $ Just $ acc <> l
@@ -394,3 +488,102 @@ parseTe sym inp =
                G.try (Command_Def <$> Sym.g_NameTe <* G.lexeme (G.char '=') <*> Sym.g_term <* G.eoi) G.<+>
                (Command_Eval <$> Sym.g_term <* G.eoi)
 -}
+
+
+evalTeUnit :: Source src => SymInj ss () => TermVT src ss '[]
+evalTeUnit = TermVT $ Sym.teUnit -- Term noConstraint Sym.tyUnit $ teSym @() $ Sym.unit
+
+{-
+evalTeUnit :: Source src => EvalVT src
+evalTeUnit = EvalVT (Sym.tyUnit @_ @'[]) $ eval Sym.unit
+
+-- * Type 'EvalVT'
+data EvalVT src = forall vs t. EvalVT (Type src vs t) t
+
+appEvalVT ::
+ SourceInj (TypeVT src) src =>
+ Constable (->) =>
+ EvalVT src ->
+ EvalVT src ->
+ Either (Error_Beta src) (EvalVT src)
+appEvalVT (EvalVT tf te_fun) (EvalVT ta te_arg) =
+       let (tf',ta') = appendVars tf ta in
+       case unTyFun tf' of
+        Nothing -> Left $ Error_Beta_Term_not_a_function $ TypeVT tf'
+        Just (af,_rf) -> do
+               mgu <-
+                       (Error_Beta_Unify `left`) $
+                       case (unQualsTy af, unQualsTy ta') of
+                        (TypeK af', TypeK ta'') -> unifyType mempty af' ta''
+               let tf'' = subst mgu tf'
+               let ta'' = subst mgu ta'
+               appEval tf'' te_fun ta'' te_arg $ \tr te_res ->
+                       normalizeVarsTy tr $ \tr' ->
+                               EvalVT tr' te_res
+
+appEval ::
+ forall src vs fun arg ret.
+ SourceInj (TypeVT src) src =>
+ Constable (->) =>
+ Type src vs fun -> fun ->
+ Type src vs arg -> arg ->
+ (forall res. Type src vs res -> res -> ret) ->
+ Either (Error_Beta src) ret
+appEval tf fun ta arg k =
+       case tf of
+        a2b :@ a2b_a :@ a2b_b
+               | Just HRefl <- proj_ConstKiTy @(K (->)) @(->) a2b ->
+               case a2b_a `eqType` ta of
+                Nothing   -> Left $ Error_Beta_Type_mismatch (TypeVT a2b_a) (TypeVT ta)
+                Just Refl -> Right $ k a2b_b $ fun arg
+        _ -> Left $ Error_Beta_Term_not_a_function $ TypeVT tf
+-}
+
+
+
+-- * Class 'Sym_Eval'
+type instance Sym Eval = Sym_Eval
+class Sym_Eval term where
+       uneval :: a -> term a
+       default uneval :: Sym_Eval (UnT term) => Trans term => a -> term a
+       uneval = trans . uneval
+
+-- Interpreting
+instance Sym_Eval Eval where
+       uneval a = Eval a
+{-
+instance Sym_Eval View where
+       uneval = View $ \_p _v -> "()"
+instance (Sym_Eval r1, Sym_Eval r2) => Sym_Eval (Dup r1 r2) where
+       uneval = uneval `Dup` uneval
+-}
+
+-- Transforming
+instance (Sym_Eval term, Sym_Lambda term) => Sym_Eval (BetaT term)
+
+-- Typing
+instance NameTyOf Eval where
+       nameTyOf _c = [] `Mod` "Eval"
+instance ClassInstancesFor Eval where
+instance TypeInstancesFor Eval
+instance FixityOf Eval
+
+-- Compiling
+instance
+ ( SymInj ss Eval
+ ) => Gram_Term_AtomsFor src ss g Eval where
+instance ModuleFor src ss Eval
+
+-- ** 'Type's
+tyEval :: Source src => LenInj vs => Type src vs Eval
+tyEval = tyConst @(K Eval) @Eval
+
+-- ** 'Term's
+teEval_uneval ::
+ Source src => SymInj ss Eval =>
+ Type src vs a -> a ->
+ Term src ss ts vs (() #> a)
+teEval_uneval ty a =
+       Term (noConstraintLen $ lenVars ty) ty $
+       symInj @Eval $
+       TeSym $ \_c -> uneval a