1 {-# LANGUAGE NamedFieldPuns #-}
2 module Hcompta.Format.JCC.Journal where
4 import qualified Control.Monad
5 import Control.Monad (Monad(..))
6 import Data.Foldable hiding (fold)
7 import Data.Functor (Functor(..))
8 import Data.List (reverse, foldl')
9 import Data.Maybe (Maybe(..))
10 import Data.Monoid (Monoid(..))
11 import qualified Data.Monoid (getFirst, First(..))
12 import Data.Typeable ()
13 import Prelude (($), (.), flip)
15 import Hcompta.Format.JCC (Journal(..))
16 import qualified Hcompta.Format.JCC as JCC
17 -- import Hcompta.Lib.Consable (Consable(..))
21 -- | Return the given accumulator folded over
22 -- the given 'Journal' and its 'journal_includes' 'Journal's.
23 fold :: (Journal j -> a -> a) -> Journal j -> a -> a
24 fold f j@Journal{journal_includes} a =
26 (flip (fold f)) (f j a)
29 -- | Return the given accumulator folded over
30 -- the given 'Journal' and its 'journal_includes' 'Journal's.
31 foldM :: Monad m => (Journal j -> a -> m a) -> Journal j -> a -> m a
32 foldM f j@Journal{journal_includes} a = do
38 -- | Return the given accumulator folded with the given function
39 -- over the given 'Journal' and its 'journal_includes' 'Journal's.
40 fold_map :: Monoid a => (Journal j -> a -> a) -> Journal j -> a -> a
41 fold_map f j@(Journal{journal_includes}) =
42 (f j) `mappend` foldMap (fold_map f) journal_includes
44 -- | Return the first non-'Nothing' value returned by the given function
45 -- when applied to the given 'Journal' or its 'journal_includes' 'Journal's,
46 -- with the parent 'Journal's.
47 find :: (Journal j -> Maybe a) -> Journal j -> Maybe (a, [Journal j])
51 Just (a, path) -> Just (a, reverse path))
54 find_ path j@Journal{journal_includes} =
56 Just a -> Just (a, path)
58 Data.Monoid.getFirst $
59 foldMap (Data.Monoid.First . (find_ (j:path))) $
62 -- | Return the given 'Journal' and its 'journal_includes' 'Journal's
63 -- mapped by the given function.
64 traverse :: (Journal j -> Journal j) -> Journal j -> Journal j
67 j@Journal{journal_includes} ->
68 j{journal_includes = fmap (traverse f) journal_includes})
73 unions :: (Foldable f, Monoid j) => f (Journal j) -> Journal j
74 unions = foldl' (flip mappend) JCC.journal
76 -- | Return the 'Journal' recursively 'mappend'-ed
77 -- with its 'journal_includes', now empty.
78 flatten :: Monoid j => Journal j -> Journal j
80 (mconcat $ (:) jnl $ fmap flatten $ journal_includes jnl)
81 { journal_includes = []