From 2ddeb4841c24a70a13a3ee3fa20b2628d94a78ce Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Mon, 2 Jul 2007 16:43:14 +0000 Subject: [PATCH] move types to bottom --- Account.hs | 5 -- AccountName.hs | 1 - Amount.hs | 45 +---------------- Currency.hs | 27 +++++++++++ Entry.hs | 20 -------- EntryTransaction.hs | 3 +- Ledger.hs | 6 --- Makefile | 2 +- Models.hs | 4 +- TimeLog.hs | 11 +---- Transaction.hs | 5 -- Types.hs | 115 ++++++++++++++++++++++++++++++++++++++++++++ Utils.hs | 13 ++--- hledger.hs | 20 +------- 14 files changed, 158 insertions(+), 119 deletions(-) create mode 100644 Currency.hs diff --git a/Account.hs b/Account.hs index 15d3adeaa..0cb262e39 100644 --- a/Account.hs +++ b/Account.hs @@ -14,11 +14,6 @@ import Ledger -- an Account caches an account's name, balance (including sub-accounts) -- and transactions (excluding sub-accounts) -data Account = Account { - aname :: AccountName, - atransactions :: [EntryTransaction], - abalance :: Amount -} instance Show Account where show (Account a ts b) = printf "Account %s with %d transactions" a $ length ts diff --git a/AccountName.hs b/AccountName.hs index 94ba6fd28..a4ba26886 100644 --- a/AccountName.hs +++ b/AccountName.hs @@ -5,7 +5,6 @@ import Types -- AccountNames are strings like "assets:cash:petty"; from these we build -- the chart of accounts, which should be a simple hierarchy. -type AccountName = String accountNameComponents :: AccountName -> [String] accountNameComponents = splitAtElement ':' diff --git a/Amount.hs b/Amount.hs index 07bb8176c..17bc369be 100644 --- a/Amount.hs +++ b/Amount.hs @@ -2,8 +2,9 @@ module Amount where import Utils import Types +import Currency -{- +{- a simple amount is a currency, quantity pair: $1 @@ -40,43 +41,6 @@ tests = runTestTT $ test [ parseAmount "$1" ~?= dollars 1 -- currently 0 ] --- currency - -data Currency = Currency { - symbol :: String, - rate :: Double -- relative to the dollar - } deriving (Eq,Show) - -currencies = - [ - Currency "$" 1 - ,Currency "EUR" 0.760383 - ,Currency "£" 0.512527 - ,Currency "h" 60 -- hours - ,Currency "m" 1 -- minutes - ] - -getcurrency :: String -> Currency -getcurrency s = head $ [(Currency symbol rate) | (Currency symbol rate) <- currencies, symbol==s] - --- convenience -dollars = Amount $ getcurrency "$" -euro = Amount $ getcurrency "EUR" -pounds = Amount $ getcurrency "£" -hours = Amount $ getcurrency "h" -minutes = Amount $ getcurrency "m" - -conversionRate :: Currency -> Currency -> Double -conversionRate oldc newc = (rate newc) / (rate oldc) - - --- amount - -data Amount = Amount { - currency :: Currency, - quantity :: Double - } deriving (Eq) - instance Show Amount where show = showAmountRoundedOrZero nullamt = dollars 0 @@ -107,8 +71,3 @@ toCurrency :: Currency -> Amount -> Amount toCurrency newc (Amount oldc q) = Amount newc (q * (conversionRate oldc newc)) - --- mixed amounts - ---data MixedAmount = MixedAmount [Amount] deriving (Eq,Ord) - diff --git a/Currency.hs b/Currency.hs new file mode 100644 index 000000000..d90ad7f81 --- /dev/null +++ b/Currency.hs @@ -0,0 +1,27 @@ +module Currency +where +import Utils +import Types + +currencies = + [ + Currency "$" 1 + ,Currency "EUR" 0.760383 + ,Currency "£" 0.512527 + ,Currency "h" 60 -- hours + ,Currency "m" 1 -- minutes + ] + +getcurrency :: String -> Currency +getcurrency s = head $ [(Currency symbol rate) | (Currency symbol rate) <- currencies, symbol==s] + +conversionRate :: Currency -> Currency -> Double +conversionRate oldc newc = (rate newc) / (rate oldc) + +-- convenient amount constructors +dollars = Amount $ getcurrency "$" +euro = Amount $ getcurrency "EUR" +pounds = Amount $ getcurrency "£" +hours = Amount $ getcurrency "h" +minutes = Amount $ getcurrency "m" + diff --git a/Entry.hs b/Entry.hs index dc4b4ca96..6135a089e 100644 --- a/Entry.hs +++ b/Entry.hs @@ -6,8 +6,6 @@ import Types import Transaction -type EntryStatus = Bool - -- a register entry is displayed as two or more lines like this: -- date description account amount balance -- DDDDDDDDDD dddddddddddddddddddd aaaaaaaaaaaaaaaaaaaaaa AAAAAAAAAAA AAAAAAAAAAAA @@ -19,14 +17,6 @@ type EntryStatus = Bool -- amtWidth = 11 -- balWidth = 12 -data Entry = Entry { - edate :: Date, - estatus :: EntryStatus, - ecode :: String, - edescription :: String, - etransactions :: [Transaction] - } deriving (Eq) - instance Show Entry where show = showEntry showEntry e = (showDate $ edate e) ++ " " ++ (showDescription $ edescription e) ++ " " @@ -43,19 +33,9 @@ autofillEntry e = -- modifier & periodic entries -data ModifierEntry = ModifierEntry { -- aka "automated entry" - valueexpr :: String, - m_transactions :: [Transaction] - } deriving (Eq) - instance Show ModifierEntry where show e = "= " ++ (valueexpr e) ++ "\n" ++ unlines (map show (m_transactions e)) -data PeriodicEntry = PeriodicEntry { - periodexpr :: String, - p_transactions :: [Transaction] - } deriving (Eq) - instance Show PeriodicEntry where show e = "~ " ++ (periodexpr e) ++ "\n" ++ unlines (map show (p_transactions e)) diff --git a/EntryTransaction.hs b/EntryTransaction.hs index a1cfffec2..9b631a651 100644 --- a/EntryTransaction.hs +++ b/EntryTransaction.hs @@ -6,6 +6,7 @@ import Types import Entry import Transaction import Amount +import Currency -- We convert Transactions into EntryTransactions, which are (entry, @@ -13,8 +14,6 @@ import Amount -- reference their entry like in OO. These are referred to as just -- "transactions" in code above. -type EntryTransaction = (Entry,Transaction) - entry (e,t) = e transaction (e,t) = t date (e,t) = edate e diff --git a/Ledger.hs b/Ledger.hs index dc7335f8f..1a0ebf34c 100644 --- a/Ledger.hs +++ b/Ledger.hs @@ -9,12 +9,6 @@ import Entry import EntryTransaction -data Ledger = Ledger { - modifier_entries :: [ModifierEntry], - periodic_entries :: [PeriodicEntry], - entries :: [Entry] - } deriving (Eq) - instance Show Ledger where show l = printf "Ledger with %d entries" ((length $ entries l) + diff --git a/Makefile b/Makefile index ffe3eb477..582993ba3 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ haddock: haddock -h -o doc *.hs overview: - @./overview.hs hledger.hs + @./overview.hs Types.hs loc: @darcs trackdown 'find . -name "*hs" |xargs wc -l |echo OUTPUT `tail -1`; false' |ruby -nae'puts $$F[1] if /^OUTPUT/' diff --git a/Models.hs b/Models.hs index 0ce22872d..f9a83844e 100644 --- a/Models.hs +++ b/Models.hs @@ -1,6 +1,7 @@ --- data types & behaviours +-- all data types & behaviours module Models ( module Types, + module Currency, module Amount, module AccountName, module Transaction, @@ -14,6 +15,7 @@ where import qualified Data.Map as Map import Types +import Currency import Amount import AccountName import Transaction diff --git a/TimeLog.hs b/TimeLog.hs index eb057cc39..d30c3c50f 100644 --- a/TimeLog.hs +++ b/TimeLog.hs @@ -2,24 +2,15 @@ module TimeLog where import Utils import Types +import Currency import Amount import Transaction import Entry import Ledger -data TimeLogEntry = TimeLogEntry { - tcode :: Char, - tdatetime :: DateTime, - tcomment :: String - } deriving (Eq,Ord) - instance Show TimeLogEntry where show t = printf "%s %s %s" (show $ tcode t) (tdatetime t) (tcomment t) -data TimeLog = TimeLog { - timelog_entries :: [TimeLogEntry] - } deriving (Eq) - instance Show TimeLog where show tl = printf "TimeLog with %d entries" $ length $ timelog_entries tl diff --git a/Transaction.hs b/Transaction.hs index 8333b31e2..70e7794eb 100644 --- a/Transaction.hs +++ b/Transaction.hs @@ -7,11 +7,6 @@ import AccountName import Amount -data Transaction = Transaction { - taccount :: AccountName, - tamount :: Amount - } deriving (Eq) - instance Show Transaction where show = showTransaction showTransaction t = (showAccountName $ taccount t) ++ " " ++ (showAmount $ tamount t) diff --git a/Types.hs b/Types.hs index b2796531d..135edc1b7 100644 --- a/Types.hs +++ b/Types.hs @@ -2,6 +2,121 @@ module Types where import Utils +{- + +First, here is the module hierarchy. The initial implementation defined +types in each module and so was strictly layered. Now, all types have been +moved to the bottom, with modules still used to group related functions +(aka methods - "make overview" to list these). + +hledger + Options + Tests + Parse + Models + TimeLog + TimeLogEntry + Account + Ledger + EntryTransaction + Entry + Transaction + AccountName + Amount + Currency + Types + Utils + +(Will this allow a more muddled design ? Possibly, though starting out +layered probably helped, but note previous comment: + + Each layer can only reference things below it. A seeming problem: + CookedLedger must be at the top so it can cache any of the others. Code + below it can not use its fast functions, and code above it should use + only its functions for good performance. Upper-level code loses the + benefit of many lower-level functions and has to reimplement them as + fast versions.) + +-} type Date = String + type DateTime = String + +data Currency = Currency { + symbol :: String, + rate :: Double -- relative to the dollar + } deriving (Eq,Show) + +-- some amount of money, time, stock, oranges, etc. +data Amount = Amount { + currency :: Currency, + quantity :: Double + } deriving (Eq) + +-- AccountNames are strings like "assets:cash:petty"; from these we build +-- the chart of accounts, which should be a simple hierarchy. +type AccountName = String + +-- a flow of an amount to an account +data Transaction = Transaction { + taccount :: AccountName, + tamount :: Amount + } deriving (Eq) + +-- cleared ? +type EntryStatus = Bool + +-- a ledger entry, with two or more balanced transactions +data Entry = Entry { + edate :: Date, + estatus :: EntryStatus, + ecode :: String, + edescription :: String, + etransactions :: [Transaction] + } deriving (Eq) + +-- an "automated" entry (see = in ledger manual) +data ModifierEntry = ModifierEntry { + valueexpr :: String, + m_transactions :: [Transaction] + } deriving (Eq) + +-- a periodic entry (see ~ in ledger manual) +data PeriodicEntry = PeriodicEntry { + periodexpr :: String, + p_transactions :: [Transaction] + } deriving (Eq) + +-- a parsed ledger file +data Ledger = Ledger { + modifier_entries :: [ModifierEntry], + periodic_entries :: [PeriodicEntry], + entries :: [Entry] + } deriving (Eq) + +-- we also process timeclock.el's timelogs +data TimeLogEntry = TimeLogEntry { + tcode :: Char, + tdatetime :: DateTime, + tcomment :: String + } deriving (Eq,Ord) + +data TimeLog = TimeLog { + timelog_entries :: [TimeLogEntry] + } deriving (Eq) + +-- We convert Transactions into EntryTransactions, which are (entry, +-- transaction) pairs, since I couldn't see how to have transactions +-- reference their entry like in OO. These are referred to as just +-- "transactions" in modules above EntryTransaction. +type EntryTransaction = (Entry,Transaction) + +-- an Account caches a particular account's name, balance and transactions +-- from a Ledger +data Account = Account { + aname :: AccountName, + atransactions :: [EntryTransaction], -- excludes sub-accounts + abalance :: Amount -- includes sub-accounts + } + diff --git a/Utils.hs b/Utils.hs index f638c666f..ad412829f 100644 --- a/Utils.hs +++ b/Utils.hs @@ -26,9 +26,6 @@ splitAtElement e l = where (first,rest) = break (e==) l' --- testing support - - -- tree tools root = rootLabel @@ -37,8 +34,7 @@ branches = subForest -- remove all nodes past a certain depth treeprune :: Int -> Tree a -> Tree a treeprune 0 t = Node (root t) [] -treeprune d t = - Node (root t) (map (treeprune $ d-1) $ branches t) +treeprune d t = Node (root t) (map (treeprune $ d-1) $ branches t) -- apply f to all tree nodes treemap :: (a -> b) -> Tree a -> Tree b @@ -57,4 +53,9 @@ treeany f t = (f $ root t) || (any (treeany f) $ branches t) -- treedrop -- remove the leaves which do fulfill predicate. -- treedropall -- do this repeatedly. -strace a = trace (show a) a \ No newline at end of file +-- debugging + +strace a = trace (show a) a + +-- testing + diff --git a/hledger.hs b/hledger.hs index 52124d067..83214faa9 100644 --- a/hledger.hs +++ b/hledger.hs @@ -4,25 +4,7 @@ hledger - ledger-compatible money management tool (& haskell study) GPLv3, (c) Simon Michael & contributors A port of John Wiegley's ledger at http://newartisans.com/ledger.html -Here is a rough overview of the module/model hierarchy: - -hledger - Options - Tests - Parse - Models - TimeLog - TimeLogEntry - Account - Ledger - EntryTransaction - Entry - Transaction - AccountName - Amount - Types - Utils - +See Types.hs for a code overview. -} module Main