1 {-# LANGUAGE ExistentialQuantification #-}
2 module Hcompta.LCC.Compta where
4 import Control.Monad (Monad(..))
5 import Data.Bool (Bool(..))
6 import Data.Either (either)
8 import Data.Function (($), (.), id)
9 import Data.Functor ((<$>))
10 import Data.Functor.Identity (Identity(..))
11 import Prelude (error)
12 import Text.Show (Show(..))
13 import qualified Control.Monad.Classes as MC
14 import qualified Control.Monad.Trans.State.Strict as SS
15 import qualified Hcompta.LCC.Lib.Strict as S
17 import Hcompta.LCC.Amount
18 import Hcompta.LCC.Balance
19 import Hcompta.LCC.Chart
20 import Hcompta.LCC.Journal
22 import Hcompta.LCC.Transaction
23 import Language.Symantic as Sym
24 import qualified Hcompta as H
30 , lcc_journals :: !(Journals src (Transactions src))
31 , lcc_style :: !Style_Amounts
32 , lcc_base :: !CanonFile
34 instance H.Get Style_Amounts (LCC src) where
36 instance H.Sumable Balance (LCC src) where
37 b += l = b H.+= lcc_journals l
39 -- ** Type 'State_Sym'
42 { state_sym_types :: !(Sym.Imports Sym.NameTy, Sym.ModulesTy src)
43 , state_sym_terms :: !(Sym.Imports Sym.NameTe, Sym.Modules src ss)
50 Sym.ModulesInj src ss =>
51 Sym.ModulesTyInj ss =>
54 let mods = either (error . show) id Sym.modulesInj in
56 { state_sym_types = (Sym.importTypes @ss [], Sym.modulesTyInj @ss)
57 , state_sym_terms = (Sym.importModules [] mods, mods)
61 type instance MC.CanDo (S.StateT (State_Sym src ss) m) (MC.EffState (State_Sym src ss)) = 'True
62 instance Monad m => MC.MonadStateN 'MC.Zero (State_Sym src ss) (S.StateT (State_Sym src ss) m) where
63 stateN _px = S.StateT . SS.state
65 -- (Sym.Imports Sym.NameTe, Sym.Modules src ss)
66 type instance MC.CanDo (S.StateT (State_Sym src ss) m) (MC.EffState (Sym.Imports Sym.NameTe, Sym.Modules src ss)) = 'True
67 instance Monad m => MC.MonadStateN 'MC.Zero (Sym.Imports Sym.NameTe, Sym.Modules src ss) (S.StateT (State_Sym src ss) m) where
68 stateN _px f = S.StateT $ SS.state $ \st ->
69 (\a -> st{state_sym_terms=a}) <$> f (state_sym_terms st)
71 -- (Sym.Imports Sym.NameTy, Sym.ModulesTy src)
72 type instance MC.CanDo (S.StateT (State_Sym src ss) m) (MC.EffState (Sym.Imports Sym.NameTy, Sym.ModulesTy src)) = 'True
73 instance Monad m => MC.MonadStateN 'MC.Zero (Sym.Imports Sym.NameTy, Sym.ModulesTy src) (S.StateT (State_Sym src ss) m) where
74 stateN _px f = S.StateT $ SS.state $ \st ->
75 (\a -> st{state_sym_types=a}) <$> f (state_sym_types st)
78 newtype Database db a = Database (S.StateT db Identity a)
81 newtype Query db a = Query { runQuery :: db -> a }
84 class Queryable db a where
86 instance Queryable (LCC src) Balance where
87 query = Query $ H.sum . lcc_journals
94 Base (Type src vs db) db
97 data DataBase = forall db. Typeable db => DataBase db
100 newtype Code src ss m a
101 = Code (S.StateT (State_Sym src (Sym.Proxy (Code src ss) ': ss)) m a)
102 deriving (Functor, Applicative, Monad, Typeable)
106 -- * Class 'Balanceable'
107 class Balanceable a where
108 balance :: a -> Balance
109 instance Balanceable (LCC src) where
110 balance = H.sum . lcc_journals @src
114 type instance MC.CanDo (S.StateT (LCC src) m) (MC.EffState (LCC src)) = 'True
115 instance Monad m => MC.MonadStateN 'MC.Zero (LCC src) (S.StateT (LCC src) m) where
116 stateN _px = S.StateT . SS.state
123 main :: (Compta a -> b) -> FilePath -> b
125 main :: (Compta a -> b) -> FilePath -> IO b
127 (ComptaM a -> ComptaM b) -> ComptaM a -> ComptaM b
132 balance :: Compta Journals -> Compta Balance
133 balance :: Balanceable f => Compta f Balance
139 ./toto :: IO (Context a)
140 balance :: Context LCC Balance
142 readLCC :: Context LCC ()
143 readLedger :: Context Ledger ()
144 readSQL :: Context SQL ()
146 write :: Context Ledger ()
150 journals :: Context LCC Journals
151 chart :: Context LCC Chart
152 styles :: Context LCC styles
153 stats :: Context LCC stats
159 load ./toto >>= \() ->
164 data Context src ss fmt a
166 { state_sym :: !(State_Sym src ss)
167 , context_return :: fmt a
169 instance Functor (Context src ss fmt)
170 instance Applicative (Context src ss fmt)
171 pure = context_return
173 instance Monad (Context src ss fmt) where
174 return = context_return
175 c >>= f = f (context_return c)
179 instance Functor LCC where
180 fmap f c = c{lcc_return = f (lcc_return c)}
181 instance Applicative LCC where
184 , lcc_journals = mempty
190 { lcc_chart = lcc_chart f <> lcc_chart a
191 , lcc_journals = lcc_journals f <> lcc_journals a
192 , lcc_style = lcc_style f <> lcc_style a
193 , lcc_return = lcc_return f (lcc_return a)
195 instance Monad LCC where
198 let c' = f (lcc_return c) in
200 { lcc_chart = lcc_chart c <> lcc_chart c'
201 , lcc_journals = lcc_journals c <> lcc_journals c'
202 , lcc_style = lcc_style c <> lcc_style c'
207 instance Balanceable LCC where
208 balance f = f{lcc_data = H.sum $ lcc_compta f}
211 { lcc_io_data :: Set FilePath
215 class Backend a where
216 instance Backend (IO a) where
217 instance Backend () where
218 instance Backend (SQL a)
220 class Journalable a where
221 journal_fold :: (Transaction -> j -> j) -> a -> j
225 type ComptaS src ss = SS.State (State_Compta src ss)
226 -- type ComptaIO src ss = ComptaT src ss IO
228 runComptaS :: ComptaS src ss a -> State_Compta src ss -> (a, State_Compta src ss)
229 runComptaS = SS.runState
231 -- ** Type 'State_Compta'
232 data State_Compta src ss
233 = forall js. Journalable js
235 { state_compta_sty :: !Style_Amounts
236 , state_compta_sym :: !(State_Sym src ss)
237 , state_compta_jnl :: !js
238 } deriving (Eq, Show)
243 Sym.ImportTypes ss =>
244 Sym.ModulesInj src ss =>
245 Sym.ModulesTyInj ss =>
247 compta = State_Compta
248 { compta_sym = state_sym
249 , compta_data = mempty