1 --{-# LANGUAGE ApplicativeDo #-}
2 {-# LANGUAGE AllowAmbiguousTypes #-}
3 {-# LANGUAGE BlockArguments #-}
4 {-# LANGUAGE ConstraintKinds #-}
5 {-# LANGUAGE DataKinds #-}
6 {-# LANGUAGE DefaultSignatures #-}
7 {-# LANGUAGE FlexibleContexts #-}
9 {-# LANGUAGE KindSignatures #-}
10 {-# LANGUAGE LambdaCase #-}
11 {-# LANGUAGE MultiParamTypeClasses #-}
12 {-# LANGUAGE NoImplicitPrelude #-}
13 {-# LANGUAGE OverloadedLabels #-}
14 {-# LANGUAGE OverloadedLists #-}
15 {-# LANGUAGE OverloadedStrings #-}
16 {-# LANGUAGE PatternSynonyms #-}
17 {-# LANGUAGE PolyKinds #-}
18 {-# LANGUAGE PostfixOperators #-}
19 {-# LANGUAGE RebindableSyntax #-}
20 {-# LANGUAGE StandaloneDeriving #-}
21 {-# LANGUAGE TupleSections #-}
22 {-# LANGUAGE TypeFamilies #-}
23 {-# LANGUAGE UndecidableInstances #-}
24 {-# LANGUAGE UnicodeSyntax #-}
25 {-# LANGUAGE ViewPatterns #-}
26 {-# OPTIONS_GHC -Wno-missing-signatures #-}
27 {-# OPTIONS_GHC -Wno-unused-do-bind #-}
28 {-# OPTIONS_GHC -Wno-orphans #-}
29 {-# OPTIONS_GHC -Wno-unused-imports #-}
30 module Symantic.Compta.Lang
31 ( module Symantic.Compta.Lang
32 , module Symantic.Compta.Lang.Math
33 , module Symantic.Compta.Lang.Rebindable
35 import Control.Applicative (Applicative(..))
36 import Control.DeepSeq (NFData(..))
37 import Control.Monad (Monad(..))
38 import Data.Decimal (Decimal)
40 import Data.Function (($), (.), id)
41 import Data.Functor (Functor, (<$>))
44 import Data.List.NonEmpty (NonEmpty)
45 import Data.Map.Strict (Map)
46 import Data.Maybe (Maybe)
48 import Data.Semigroup (Semigroup(..))
49 import Data.Monoid (Monoid)
50 import Data.String (String)
51 import Data.Typeable (Typeable)
52 import GHC.Generics (Generic)
53 import GHC.Stack (HasCallStack)
54 import GHC.TypeLits (Symbol, ErrorMessage(..))
55 import Numeric.Natural (Natural)
56 import Prelude (Integer, Enum(..))
57 import Text.Show (Show(..))
58 import Type.Reflection
59 import qualified Data.Char as Char
60 import qualified Data.List as List
61 import qualified Data.Maybe as Maybe
62 import qualified Data.String as String
63 import qualified Data.Time.Calendar as Time
64 import qualified GHC.Exts as GHC
65 import qualified Prelude
67 import Symantic.Compta.Lang.Math
68 import Symantic.Compta.Lang.Rebindable
69 import Symantic.Compta.Utils.Error
71 type family Ty (repr::Type -> Type) (a::Type) :: Type
74 data TyAmount = TyAmount
75 data TyAccount = TyAccount
77 data TyPost = TyPost deriving (Show)
78 data TyPosts = TyPosts deriving (Show)
79 data TyMove = TyMove deriving (Show)
80 data TyMoves = TyMoves deriving (Show, Semigroup, Monoid)
81 --type family Tr (repr::Type -> Type) (ty::Type) :: Type
85 type Repr = Type -> Type
87 --type ErrorNumAmount (unit::Symbol) = 'Text "err unit:" ':$$: 'ShowType unit
88 --instance TypeError (ErrorNumAmount unit) => Num (AmountOf unit repr)
90 -- | Usual syntax for type-preserving term-abstraction.
91 class Abstractable repr where
92 -- | Lambda term (abstract).
93 lam :: (repr a -> repr b) -> repr (a -> b)
94 -- | Term application (unabstract).
95 (.@) :: repr (a -> b) -> repr a -> repr b; infixl 9 .@
97 type DataRepr = Type -> Type
98 data family Data (able :: DataRepr -> Constraint) :: DataRepr -> DataRepr
99 data SomeData repr a = forall able. (Trans ((Data able) repr) repr, Typeable able) => SomeData (Data able repr a)
100 -- | @(unSomeData c :: 'Maybe' ('Data' able repr a))@
101 -- extract the data-constructor from the given 'SomeData'
102 -- iif. it belongs to the @('Data' able repr a)@ data-instance.
106 SomeData repr a -> Maybe (Data able repr a)
107 unSomeData (SomeData (c::Data c repr a)) =
108 case typeRep @able `eqTypeRep` typeRep @c of
109 Maybe.Just HRefl -> Maybe.Just c
110 Maybe.Nothing -> Maybe.Nothing
111 -- | Convenient utility to pattern-match a 'SomeData'.
112 pattern Data :: Typeable able => Data able repr a -> SomeData repr a
113 pattern Data x <- (unSomeData -> Maybe.Just x)
115 class Unliftable r repr where
116 unlift :: r repr a -> repr a
117 class Liftable r repr where
118 lift :: repr a -> r repr a
120 class Trans from to where
121 trans :: from a -> to a
123 class Accountable repr where
124 account :: Ty repr TyAccount -> repr TyAccount
125 class Amountable repr where
126 amount :: Ty repr TyAmount -> repr TyAmount
128 class Inject a repr ty where
129 inject :: a -> repr ty
132 type family AccountOf (t::k) :: Type
133 type family AccountSectionOf (t::k) :: Type
134 type family AmountOf (t::k) :: Type
135 type family QuantityOf (t::k) :: Type
136 type family UnitOf (t::k) :: Type
137 type family PostOf (t::k) :: Type
138 type family MoveOf (t::k) :: Type
139 type family TransactionsOf (t::k) :: Type
140 type family ChartSectionOf (t::k) :: Type
141 type family ChartOf (t::k) :: Type
142 type instance UnitOf (Maybe amt) = UnitOf amt
143 type instance QuantityOf (Maybe amt) = QuantityOf amt
144 type instance UnitOf (Map unit qty) = unit
145 type instance QuantityOf (Map unit qty) = qty
148 type family AccountOf (repr::Repr) :: Type
149 type family AccountSectionOf (repr::Repr) :: Type
150 type family AmountOf (repr::Repr) :: Type
151 type family QuantityOf (repr::Repr) :: Type
152 type family UnitOf (repr::Repr) :: Type
153 type family PostOf (repr::Repr) :: Type
154 type family MoveOf (repr::Repr) :: Type
155 type family TransactionsOf (repr::Repr) :: Type
156 type family ChartSectionOf (repr::Repr) :: Type
157 type family ChartOf (repr::Repr) :: Type
159 -- * Class 'Accountable'
160 class Accountable repr where
161 account :: AccountOf repr -> repr (AccountOf repr)
162 class Amountable repr where
163 amount :: AmountOf repr -> repr (AmountOf repr)
165 --account :: acct -> repr a -> repr a
166 --accountFromStrings :: [String] -> repr (AccountOf repr)
167 --accountFromNatural :: Natural -> repr (AccountOf repr)
168 --class Literable repr where
169 -- lit :: a -> repr a
171 -- * Class 'Postable'
172 class Postable repr where
173 post :: HasCallStack => repr TyAccount -> repr TyAmount -> repr TyPost
177 Postable repr => Negable (repr TyAmount) =>
178 repr TyAccount -> repr TyAmount -> repr TyPost
180 HasCallStack => Postable repr =>
181 repr TyAccount -> repr TyAmount -> repr TyPost
182 (-=) acct = post acct . negate
187 -- * Class 'Moveable'
188 class Moveable repr where
189 move :: HasCallStack => repr [TyPost] -> repr TyMove
192 class Postingable repr where
193 (+=) :: repr (AccountOf repr) -> repr (AmountOf repr) -> repr (PostingsOf repr); infix 5 +=
194 (-=) :: repr (AccountOf repr) -> repr (AmountOf repr) -> repr (PostingsOf repr); infix 5 -=
197 -- * Class 'Transactionable'
199 class Transactionable repr where
200 txn :: String -> repr (PostingsOf repr) -> repr (TransactionsOf repr)
205 data Month = January | February | March | April | May | June | July | September | October | November | December
206 deriving (Enum, Show)
208 class Datable a repr where
209 year :: Year -> repr a -> repr a
210 month :: Month -> repr a -> repr a
211 day :: Int -> repr a -> repr a
212 date :: Year -> Month -> Int -> repr a -> repr a
214 -- * Class 'Chartable'
215 class Chartable chart section repr where
216 section :: HasCallStack => section -> repr chart -> repr chart
217 class ChartableLeaf chart repr where
218 anySection :: HasCallStack => repr chart
220 -- * Class 'Descriptionable'
221 class Descriptionable repr where
222 description :: HasCallStack => String -> repr ()
225 class Namable repr where
226 name :: HasCallStack => String -> repr ()
229 -- * Class 'Journalable'
237 , Datable (PostingsOf repr) repr
238 , Datable (TransactionsOf repr) repr
239 , FromInteger (repr (AccountOf repr))
240 , IsString (repr (AccountOf repr))
242 , Transactionable repr
243 ) => Journalable repr
251 , Datable (PostingsOf repr) repr
252 , Datable (TransactionsOf repr) repr
253 , FromInteger (repr (AccountOf repr))
254 , IsString (repr (AccountOf repr))
256 , Transactionable repr
257 ) => Journalable repr
260 t0 :: Journalable repr => repr (TransactionsOf repr)
266 accountFromStrings ["A"] -= eur 10
267 accountFromStrings ["B"] += usd 5
268 accountFromStrings ["C"] += (5€)
273 accountFromNatural 511 -= eur 10
276 "Capital/Tiers" -= eur 10
277 --["Capital","Tiers"] -= eur 10