1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE NamedFieldPuns #-}
3 module Hcompta.Format.Ledger.Journal where
5 -- import Control.Applicative ((<$>))
6 import qualified Data.Foldable (foldMap)
7 import Data.Foldable (Foldable(..))
8 import qualified Data.List
9 import qualified Data.Map.Strict as Data.Map
10 import qualified Data.Monoid (getFirst, First(..))
11 import Data.Monoid (Monoid, mappend)
12 import Data.Typeable ()
14 import qualified Hcompta.Format.Ledger as Ledger
15 import Hcompta.Format.Ledger (Journal(..))
19 -- | Return the given accumulator folded over
20 -- the given 'Journal' and its 'journal_includes' 'Journal's.
21 fold :: (Journal -> a -> a) -> Journal -> a -> a
22 fold f j@Journal{journal_includes} a =
23 Data.List.foldl' (flip (Hcompta.Format.Ledger.Journal.fold f))
27 -- | Return the given accumulator folded with the given function
28 -- over the given 'Journal' and its 'journal_includes' 'Journal's.
29 fold_map :: Monoid a => (Journal -> a -> a) -> Journal -> a -> a
30 fold_map f j@(Journal{journal_includes}) =
31 (f j) `mappend` Data.Foldable.foldMap (fold_map f) journal_includes
33 -- | Return the first non-'Nothing' value returned by the given function
34 -- when applied to the given 'Journal' or its 'journal_includes' 'Journal's,
35 -- with the parent 'Journal's.
36 find :: (Journal -> Maybe a) -> Journal -> Maybe (a, [Journal])
40 Just (a, path) -> Just (a, Data.List.reverse path))
43 find_ path j@Journal{journal_includes} =
45 Just a -> Just (a, path)
47 Data.Monoid.getFirst $
48 Data.Foldable.foldMap (Data.Monoid.First . (find_ (j:path))) $
51 -- | Return the given 'Journal' and its 'journal_includes' 'Journal's
52 -- mapped by the given function.
53 traverse :: (Journal -> Journal) -> Journal -> Journal
56 j@Journal{journal_includes} ->
57 j{journal_includes = Data.List.map (traverse f) journal_includes})
62 union :: Journal -> Journal -> Journal
64 Journal{ journal_transactions=t0 }
65 j@Journal{ journal_transactions=t1 } =
66 j{ journal_transactions = Data.Map.unionWith (++) t0 t1 }
68 unions :: Foldable t => t Journal -> Journal
69 unions = Data.Foldable.foldl' union Ledger.journal
71 -- | Return the 'Journal' with its 'journal_transactions'
72 -- recursively completed by the 'journal_transactions'
73 -- of its 'journal_includes', now empty.
74 flatten :: Journal -> Journal
77 { journal_transactions =
78 Data.Map.unionsWith (++) $
79 flat journal_transactions jnl
80 , journal_includes = []
83 flat :: (Journal -> a) -> Journal -> [a]
84 flat g j = g j:Data.List.concatMap (flat g) (journal_includes j)