1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE NamedFieldPuns #-}
5 {-# LANGUAGE Rank2Types #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE StandaloneDeriving #-}
8 {-# LANGUAGE TupleSections #-}
9 {-# LANGUAGE TypeFamilies #-}
10 {-# OPTIONS_GHC -fno-warn-orphans #-}
11 module Hcompta.Filter.Read where
13 import Control.Applicative ((<$>), (<*))
14 import Control.Exception (assert)
15 import Control.Monad (Monad(..), liftM, join, when, (=<<), (>=>), void, forM)
19 import Data.Either (Either(..))
20 import Data.Eq (Eq(..))
21 import qualified Data.Foldable
22 import Data.Foldable (Foldable(..))
23 import Data.Functor (Functor(..))
24 import Data.Functor.Identity (Identity)
25 import Data.List ((++), concat, map, reverse)
26 import Data.Maybe (Maybe(..), catMaybes)
27 import Data.Ord (Ord(..))
28 import Data.String (String, fromString)
29 import Data.Text (Text)
30 import qualified Data.Text as Text
31 import qualified Data.Time.Clock as Time
32 import Data.Typeable ()
33 import Prelude (($), (.), Integer, IO, Num(..), undefined)
34 import qualified Text.Parsec.Expr as R
35 import qualified Text.Parsec as R hiding
47 import Text.Parsec (Stream, ParsecT, (<|>), (<?>))
48 import Text.Show (Show(..))
50 -- import qualified Hcompta.Amount as Amount
51 import Hcompta.Date (Date)
52 import qualified Hcompta.Date as Date
54 import qualified Hcompta.Filter as Filter
55 import qualified Hcompta.Filter.Amount as Filter.Amount
56 import qualified Hcompta.Filter.Amount.Read as Amount.Read
57 import qualified Hcompta.Filter.Date.Read as Date.Read
58 import Hcompta.Lib.Interval (Interval)
59 import qualified Hcompta.Lib.Interval as Interval
60 import qualified Hcompta.Lib.Parsec as R
61 import qualified Hcompta.Lib.Regex as Regex
62 -- import Hcompta.Polarize
63 -- import qualified Hcompta.Quantity as Quantity
64 import qualified Hcompta.Posting as Posting
65 import qualified Hcompta.Unit as Unit
70 { context_date :: Date
71 } deriving (Data, Eq, Show, Typeable)
76 { context_date = Date.nil
82 | Error_Filter_Date Date.Read.Error
83 | Error_Filter_Date_Interval (Integer, Integer)
88 ( Stream s (R.Error_State Error Identity) Char
91 => ParsecT s Context (R.Error_State Error Identity) (Filter_Bool t)
92 -> s -> IO (Either [R.Error Error] (Filter_Bool t))
94 context_date <- Time.getCurrentTime
96 R.runParser_with_Error t context{context_date} "" s
98 -- * Read 'Filter_Text'
100 :: (Stream s m Char, Monad r)
101 => ParsecT s u m (String -> r Filter_Text)
104 [ R.char '~' >> return (Regex.of_StringM >=> (return . Filter_Text_Regex))
105 , R.char '=' >> return (\s -> return (Filter_Text_Exact $ Text.pack s))
106 , return (\s -> return (Filter_Text_Exact $ Text.pack s))
111 => ParsecT s u m String
112 filter_text_operator =
118 -- * Read 'Filter_Ord'
120 :: (Stream s m Char, Ord o)
121 => ParsecT s u m (o -> Filter_Ord o)
124 [ R.string "=" >> return (Filter_Ord Eq)
125 , R.string "<=" >> return (Filter_Ord Le) -- NOTE: before "<"
126 , R.string ">=" >> return (Filter_Ord Ge) -- NOTE: before ">"
127 , R.string "<" >> return (Filter_Ord Lt)
128 , R.string ">" >> return (Filter_Ord Gt)
133 => ParsecT s u m String
134 filter_ord_operator =
143 -- * Read 'Filter_Num_Abs'
145 :: (Stream s m Char, Num n)
146 => ParsecT s u m (Filter_Ord n -> m (Either (Filter_Ord n) (Filter_Num_Abs n)))
149 [ R.char '+' >> return (return . Right . Filter_Num_Abs)
150 , return (return . Left)
153 text :: Stream s m Char => String -> ParsecT s Context m Text
158 , R.many $ R.noneOf ("() " ++ none_of)
161 borders = R.between (R.char '(') (R.char ')')
162 inside = liftM concat $ R.many (R.choice_try [borders preserve_inside, R.many1 $ R.noneOf "()"])
163 preserve_inside = inside >>= (\x -> return $ '(':(x++[')']))
165 -- * Read 'Filter_Bool'
168 => [ParsecT s u m (ParsecT s u m (Filter_Bool t))]
169 -> ParsecT s u m (Filter_Bool t)
171 R.buildExpressionParser
172 filter_bool_operators
173 (filter_bool_term terms)
176 filter_bool_operators
178 => R.OperatorTable s u m (Filter.Filter_Bool t)
179 filter_bool_operators =
180 [ [ prefix "- " Filter.Not
182 , [ binary " & " Filter.And R.AssocLeft
184 , [ binary " + " Filter.Or R.AssocLeft
185 , binary " - " (\x -> Filter.And x . Filter.Not) R.AssocLeft
189 binary name fun = R.Infix (filter_bool_operator name >> return fun)
190 prefix name fun = R.Prefix (filter_bool_operator name >> return fun)
191 -- postfix name fun = Text.Parsec.Expr.Postfix (filter_bool_operator name >> return fun)
195 => String -> ParsecT s u m ()
196 filter_bool_operator name =
199 >> R.notFollowedBy filter_bool_operator_letter
203 filter_bool_operator_letter
204 :: Stream s m Char => ParsecT s u m Char
205 filter_bool_operator_letter =
206 R.oneOf ['-', '&', '+']
210 => [ParsecT s u m (ParsecT s u m (Filter_Bool t))]
211 -> ParsecT s u m (Filter_Bool t)
212 filter_bool_term terms = (do
214 ( (R.lookAhead (R.try (R.spaces >> R.char '('))
215 >> (return $ parens $
216 Data.Foldable.foldr Filter.And Filter.Any <$>
217 R.many (R.try (R.spaces >> expr)) ))
219 ) <* R.spaces) <?> "boolean-term"
222 R.lookAhead (R.try R.anyToken)
223 >> R.notFollowedBy (R.char ')')
232 (R.spaces >> R.char '(')
233 (R.spaces >> R.char ')')
235 bool :: Stream s m Char => ParsecT s u m Bool
250 jump :: Stream s m Char
255 jump prefixes next r =
256 R.choice_try (map (\s -> R.string s >> return r) prefixes)
257 <* R.lookAhead (R.try next)
259 -- * Read 'Filter_Account'
261 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
262 newtype Forall_Filter_Account
263 = Forall_Filter_Account
264 { get_Forall_Filter_Account ::
267 ) => Filter_Account_Component acct
272 => ParsecT s Context m (Filter_Bool Forall_Filter_Account)
274 f <- R.many $ R.spaces
275 >> R.lookAhead R.anyToken
276 >> filter_bool filter_account_terms
284 => [ParsecT s Context m (ParsecT s Context m (Filter_Bool Forall_Filter_Account))]
285 filter_account_terms =
286 [ jump [ "AT" ] filter_account_operator $ do
289 Bool $ Forall_Filter_Account $
290 Filter.Filter_Account_Tag f
292 f <- filter_account_path
294 Bool $ Forall_Filter_Account $
295 Filter.Filter_Account_Path f
298 filter_account_operator
300 => ParsecT s u m String
301 filter_account_operator =
303 [ filter_ord_operator
308 => ParsecT s u m (Filter_Path Account_Section)
309 filter_account_path = do
310 R.notFollowedBy $ R.space_horizontal
312 R.option (Filter_Ord Eq ()) $ R.try $
313 (\f -> f ()) <$> filter_ord
316 (R.many (R.satisfy (\c -> c /= account_section_sep && not (Data.Char.isSpace c))))
317 (R.char account_section_sep)
318 sections <- forM strings $ \s ->
320 "" -> return Filter_Path_Section_Many
321 "*" -> return Filter_Path_Section_Any
322 '~':t -> Filter_Path_Section_Text . Filter_Text_Regex <$> Regex.of_StringM t
323 t -> return $ Filter_Path_Section_Text $ Filter_Text_Exact $ Text.pack t
324 return $ Filter_Path o $
325 (if sections == [] then [Filter_Path_Section_Many] else sections)
327 account_section_sep :: Char
328 account_section_sep = ':'
330 -- * Read 'Filter_Amount'
332 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
333 newtype Forall_Filter_Amount_Decimal
334 = Forall_Filter_Amount_Decimal
335 { get_Forall_Filter_Amount_Decimal ::
338 , Amount_Quantity amt ~ Filter.Amount.Quantity
339 ) => Filter_Amount amt
344 => (Filter_Ord Filter.Amount.Quantity -> Filter_Polarized Filter.Amount.Quantity)
345 -> ParsecT s u m Forall_Filter_Amount_Decimal
346 filter_amount flt_polarized = do
347 R.notFollowedBy $ R.space_horizontal
350 >>= \(flt_ord::Filter.Amount.Quantity -> Filter_Ord Filter.Amount.Quantity) -> do
351 amt <- Amount.Read.amount
352 return $ Forall_Filter_Amount_Decimal $ And
353 (Bool $ Filter_Amount_Section_Quantity (flt_polarized $ flt_ord $ Filter.Amount.amount_quantity amt))
354 (case Unit.unit_text $ Filter.amount_unit amt of
355 u | Text.null u -> Any
356 u -> Bool $ Filter_Amount_Section_Unit (Filter_Unit (Filter_Text_Exact u)))
359 unit_ <- Amount.Read.unit >>= flt_ord . Text.unpack . Unit.unit_text
360 return $ Forall_Filter_Amount_Decimal $ Bool $ Filter_Amount_Section_Unit (Filter_Unit unit_)
363 filter_amount_operator
365 => ParsecT s u m String
366 filter_amount_operator =
368 [ filter_ord_operator
369 , filter_text_operator
372 -- * Read 'Filter_Date'
374 :: (Stream s (R.Error_State Error m) Char, Monad m)
375 => ParsecT s Context (R.Error_State Error m) (Filter_Bool Filter_Date)
379 (return $ read_date_pattern)
380 , filter_ord >>= \tst ->
383 let (year, _, _) = Date.gregorian $ context_date ctx
384 liftM (Bool . Filter_Date_UTC . tst) $
385 Date.Read.date Error_Filter_Date (Just year)
389 :: (Stream s (R.Error_State Error m) Char, Monad m)
390 => ParsecT s u (R.Error_State Error m) (Filter_Bool Filter_Date)
391 read_date_pattern = (do
392 let read2 = of_digits <$> (R.try (R.count 2 R.digit) <|> R.count 1 R.digit)
393 n0 <- read_interval Error_Filter_Date_Interval $ of_digits <$> R.many1 R.digit
394 n1 <- R.option Nothing $ R.try $ do
396 Just <$> read_interval Error_Filter_Date_Interval read2
397 n2 <- R.option Nothing $ R.try $ do
399 Just <$> read_interval Error_Filter_Date_Interval read2
400 let (year, month, dom) =
402 (Nothing, Nothing) ->
405 , Interval.unlimited )
406 (Just d1, Nothing) ->
410 (Nothing, Just _d2) -> assert False undefined
411 (Just d1, Just d2) ->
415 (hour, minute, second) <-
416 R.option (Interval.unlimited, Interval.unlimited, Interval.unlimited) $ R.try $ do
418 hour <- read_interval Error_Filter_Date_Interval read2
419 sep <- R.char Date.Read.hour_separator
420 minute <- read_interval Error_Filter_Date_Interval read2
421 second <- R.option Interval.unlimited $ R.try $ do
423 read_interval Error_Filter_Date_Interval $ of_digits <$> R.many1 R.digit
424 -- tz <- R.option Time.utc $ R.try $ do
425 -- -- R.skipMany $ R.space_horizontal
426 -- Date.Read.time_zone
435 [ just_when_limited (Filter_Date_Year . Filter_Interval_In) year
436 , just_when_limited (Filter_Date_Month . Filter_Interval_In) (Interval.fmap_unsafe (fmap fromInteger) month)
437 , just_when_limited (Filter_Date_DoM . Filter_Interval_In) (Interval.fmap_unsafe (fmap fromInteger) dom)
438 , just_when_limited (Filter_Date_Hour . Filter_Interval_In) (Interval.fmap_unsafe (fmap fromInteger) hour)
439 , just_when_limited (Filter_Date_Minute . Filter_Interval_In) (Interval.fmap_unsafe (fmap fromInteger) minute)
440 , just_when_limited (Filter_Date_Second . Filter_Interval_In) (Interval.fmap_unsafe (fmap fromInteger) second)
444 of_digits :: Num n => [Char] -> n
445 of_digits = fromInteger . R.integer_of_digits 10
446 just_when_limited f x =
447 if x == Interval.unlimited
449 else Just $ Bool $ f x
452 :: (Stream s (R.Error_State e m) Char, Monad m, Ord x)
454 -> ParsecT s u (R.Error_State e m) x
455 -> ParsecT s u (R.Error_State e m) (Interval (Interval.Unlimitable x))
456 read_interval err read_digits = do
458 [ R.string ".." >> return Interval.Unlimited_low
459 , Interval.Limited <$> read_digits
462 [ when (l /= Interval.Unlimited_low)
463 (void $ R.string "..") >> do
465 [ Interval.Limited <$> read_digits
466 , return Interval.Unlimited_high
468 case (Interval.<=..<=) l h of
469 Nothing -> R.fail_with "interval" (err $ (Interval.limited l, Interval.limited h))
473 Interval.Limited _ -> Interval.point l
474 _ -> Interval.unlimited
479 => ParsecT s u m String
480 filter_date_operator =
483 -- * Read 'Filter_Wording'
486 => ParsecT s u m Filter_Text
488 make_filter_text <- filter_text
489 R.between (R.char '"') (R.char '"') $
490 make_filter_text =<< (R.many $ R.try $ R.satisfy (/= '"'))
493 filter_wording_operator
495 => ParsecT s u m String
496 filter_wording_operator =
499 -- * Read 'Filter_Tag'
502 => ParsecT s u m Filter_Tags
504 R.notFollowedBy $ R.space_horizontal
505 Filter_Ord o () <- (\f -> f ()) <$> filter_ord
508 [ R.char '<' >> return Filter_Tag_Value_First
509 , R.char '>' >> return Filter_Tag_Value_Last
510 , return Filter_Tag_Value_Any
514 (R.many (R.satisfy (\c -> c /= account_section_sep && not (Data.Char.isSpace c))))
515 (R.char account_section_sep)
516 sections <- forM strings $ \s ->
518 "" -> return Filter_Path_Section_Many
519 "*" -> return Filter_Path_Section_Any
520 '~':t -> Filter_Path_Section_Text . Filter_Text_Regex <$> Regex.of_StringM t
521 t -> return $ Filter_Path_Section_Text $ Filter_Text_Exact $ Text.pack t
522 case reverse sections of
524 [p] -> return $ Bool $ Filter_Tag_Path $ Filter_Path o [p]
527 (Bool $ Filter_Tag_Path $ Filter_Path o $ reverse rev_path)
528 (Bool $ Filter_Tag_Value $ filter_tag_value $
530 Filter_Path_Section_Any -> Filter_Text_Any
531 Filter_Path_Section_Many -> Filter_Text_Any
532 Filter_Path_Section_Text ft -> ft
537 => ParsecT s u m String
538 filter_tag_operator = do
539 void filter_ord_operator
546 -- * Read 'Filter_Posting'
548 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
549 newtype Forall_Filter_Posting_Decimal
550 = Forall_Filter_Posting_Decimal
551 { get_Forall_Filter_Posting_Decimal ::
554 , Amount_Quantity (Posting.Posting_Amount ptg) ~ Filter.Amount.Quantity
555 ) => Filter_Posting ptg
560 => ParsecT s Context m (Filter_Bool Forall_Filter_Posting_Decimal)
562 Data.Foldable.foldr Filter.And Filter.Any <$>
565 >> R.lookAhead R.anyToken
566 >> filter_bool filter_posting_terms
570 => [ParsecT s Context m (ParsecT s Context m (Filter_Bool Forall_Filter_Posting_Decimal))]
571 filter_posting_terms =
572 [ jump [ "a", "amount" ] filter_amount_operator $ do
573 f <- filter_amount Filter_Polarized_Sum
575 Bool $ Forall_Filter_Posting_Decimal $
576 Filter.Filter_Posting_Amount $
577 get_Forall_Filter_Amount_Decimal f
578 , jump [ "[]" ] (return ()) $ do
580 Bool $ Forall_Filter_Posting_Decimal $
581 Filter_Posting_Type $
582 Filter_Posting_Type_Exact Posting_Type_Virtual
586 Bool $ Forall_Filter_Posting_Decimal $
587 Filter_Posting_Account $
588 get_Forall_Filter_Account <$> f
591 -- * Read 'Filter_Transaction'
593 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
594 newtype Forall_Filter_Transaction_Decimal
595 = Forall_Filter_Transaction_Decimal
596 { get_Forall_Filter_Transaction_Decimal ::
599 , Amount_Quantity (Posting.Posting_Amount (Transaction_Posting txn)) ~ Filter.Amount.Quantity
600 ) => Filter_Transaction txn
603 filter_transaction ::
604 ( Stream s (R.Error_State Error m) Char
606 ) => ParsecT s Context (R.Error_State Error m)
607 (Filter_Bool Forall_Filter_Transaction_Decimal)
609 {-glue_posting . -}Data.Foldable.foldr Filter.And Filter.Any <$>
612 >> R.lookAhead R.anyToken
613 >> filter_bool filter_transaction_terms
617 :: Filter_Bool Forall_Filter_Transaction_Decimal
618 -> Filter_Bool Forall_Filter_Transaction_Decimal
623 (Or b0 b1) -> Or (glue_posting b0) (glue_posting b1)
625 case glue_posting b of
627 Bool $ Forall_Filter_Transaction_Decimal $
628 case get_Forall_Filter_Transaction_Decimal f of
629 Filter_Transaction_Posting p -> Filter_Transaction_Posting (Not p)
633 case (glue_posting b0, glue_posting b1) of
634 (g0@(Bool (Forall_Filter_Transaction_Decimal f0)), g1@(Bool (Forall_Filter_Transaction_Decimal f1))) ->
635 Bool $ Forall_Filter_Transaction_Decimal $
637 (Filter_Transaction_Posting p0, Filter_Transaction_Posting p1) ->
638 Filter_Transaction_Posting (And p0 p1)
640 (g0@(Bool f0), g1@(Bool f1)) ->
641 Bool $ Forall_Filter_Transaction_Decimal $
642 case get_Forall_Filter_Transaction_Decimal f0 of
643 Filter_Transaction_Posting p0 ->
644 Filter_Transaction_Posting (Not p0)
647 case (get_Forall_Filter_Transaction_Decimal f0, get_Forall_Filter_Transaction_Decimal f1) of
648 (Filter_Transaction_Posting p0, Filter_Transaction_Posting p1) ->
649 Filter_Transaction_Posting (And p0 p1)
652 (g0, g1) -> And g0 g1
654 case (glue_posting b0, glue_posting b1) of
655 (g0@(Bool t0), g1@(Bool t1)) ->
656 case (get_Forall_Filter_Transaction_Decimal t0, get_Forall_Filter_Transaction_Decimal t1) of
657 (Filter_Transaction_Posting p0, Filter_Transaction_Posting p1) ->
658 Bool $ Forall_Filter_Transaction_Decimal $
659 Filter_Transaction_Posting $ Not p0
661 (Bool (Filter_Transaction_Posting p0), Any) ->
663 Forall_Filter_Transaction_Decimal $
664 Filter_Transaction_Posting p0
665 (Any, Bool (Filter_Transaction_Posting p1)) ->
667 Forall_Filter_Transaction_Decimal $
668 Filter_Transaction_Posting p1
669 (b0', b1') -> And b0' b1'
673 filter_transaction_terms ::
674 ( Stream s (R.Error_State Error m) Char
676 ) => [ParsecT s Context (R.Error_State Error m)
677 (ParsecT s Context (R.Error_State Error m)
678 (Filter_Bool Forall_Filter_Transaction_Decimal))]
679 filter_transaction_terms =
680 -- , jump [ "atag" ] comp_text parseFilterATag
681 -- , jump [ "code" ] comp_text parseFilterCode
682 [ jump [ "AT" ] filter_account_operator $ do
685 Bool $ Forall_Filter_Transaction_Decimal $
686 Filter_Transaction_Posting $
687 Bool $ Filter_Posting_Account $
688 Bool $ Filter_Account_Tag f
689 , jump [ "date", "d" ] filter_date_operator $ do
692 Bool $ Forall_Filter_Transaction_Decimal $
693 Filter.Filter_Transaction_Date f
694 , jump [ "tag", "T" ] filter_tag_operator $ do
697 Bool $ Forall_Filter_Transaction_Decimal $
698 Filter.Filter_Transaction_Tag f
699 , jump [ "debit", "D" ] filter_amount_operator $ do
700 f <- filter_amount Filter_Polarized_Positive
702 Bool $ Forall_Filter_Transaction_Decimal $
703 Filter_Transaction_Posting $
704 Bool $ Filter_Posting_Amount $
705 get_Forall_Filter_Amount_Decimal f
706 , jump [ "credit", "C" ] filter_amount_operator $ do
707 f <- filter_amount Filter_Polarized_Negative
709 Bool $ Forall_Filter_Transaction_Decimal $
710 Filter_Transaction_Posting $
711 Bool $ Filter_Posting_Amount $
712 get_Forall_Filter_Amount_Decimal f
713 , jump [ "wording", "W" ] filter_wording_operator $ do
716 Bool $ Forall_Filter_Transaction_Decimal $
717 Filter.Filter_Transaction_Wording f
721 Bool $ Forall_Filter_Transaction_Decimal $
722 Filter_Transaction_Posting $
723 Bool $ Filter_Posting_Account $
724 get_Forall_Filter_Account <$> f
726 -- , jump [ "date2", "edate" ] (R.char '=') parseFilterDate2
727 -- , jump [ "real" ] (R.char '=') parseFilterReal
728 -- , jump [ "status" ] (R.char '=') parseFilterStatus
729 -- , jump [ "sym" ] comp_text parseFilterSym
730 -- , R.lookAhead comp_num >> return parseFilterAmount
734 -- * Read 'Filter_Balance'
736 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
737 newtype Forall_Filter_Balance_Decimal
738 = Forall_Filter_Balance_Decimal
739 { get_Forall_Filter_Balance_Decimal ::
742 , Amount_Quantity (Balance_Amount txn) ~ Filter.Amount.Quantity
743 ) => Filter_Balance txn
748 => ParsecT s Context m (Filter_Bool Forall_Filter_Balance_Decimal)
750 Data.Foldable.foldr Filter.And Filter.Any <$>
753 >> R.lookAhead R.anyToken
754 >> filter_bool filter_balance_terms
758 => [ParsecT s Context m (ParsecT s Context m (Filter_Bool Forall_Filter_Balance_Decimal))]
759 filter_balance_terms =
760 [ jump [ "AT" ] filter_account_operator $ do
763 Bool $ Forall_Filter_Balance_Decimal $
764 Filter_Balance_Account $
765 Bool $ Filter_Account_Tag f
766 , jump [ "RD", "debit" ] filter_amount_operator $ do
767 f <- filter_amount Filter_Polarized_Positive
769 Bool $ Forall_Filter_Balance_Decimal $
770 Filter_Balance_Amount $
771 get_Forall_Filter_Amount_Decimal f
772 , jump [ "RC", "credit" ] filter_amount_operator $ do
773 f <- filter_amount Filter_Polarized_Negative
775 Bool $ Forall_Filter_Balance_Decimal $
776 Filter_Balance_Amount $
777 get_Forall_Filter_Amount_Decimal f
778 , jump [ "RB", "balance" ] filter_amount_operator $ do
779 f <- filter_amount Filter_Polarized_Sum
781 Bool $ Forall_Filter_Balance_Decimal $
782 Filter_Balance_Amount $
783 get_Forall_Filter_Amount_Decimal f
787 Bool $ Forall_Filter_Balance_Decimal $
788 Filter_Balance_Account $
789 get_Forall_Filter_Account <$> f
792 -- * Read 'Filter_GL'
794 -- | A forall type (Rank2Types) to preserve the polymorphism of the filter.
795 newtype Forall_Filter_GL_Decimal
796 = Forall_Filter_GL_Decimal
797 { get_Forall_Filter_GL_Decimal ::
800 , Amount_Quantity (GL_Amount txn) ~ Filter.Amount.Quantity
806 => ParsecT s Context m (Filter_Bool Forall_Filter_GL_Decimal)
808 Data.Foldable.foldr Filter.And Filter.Any <$>
811 >> R.lookAhead R.anyToken
812 >> filter_bool filter_gl_terms
816 => [ParsecT s Context m (ParsecT s Context m (Filter_Bool Forall_Filter_GL_Decimal))]
818 [ jump [ "AT" ] filter_account_operator $ do
821 Bool $ Forall_Filter_GL_Decimal $
823 Bool $ Filter_Account_Tag f
824 , jump [ "D", "debit" ] filter_amount_operator $ do
825 f <- filter_amount Filter_Polarized_Positive
827 Bool $ Forall_Filter_GL_Decimal $
829 get_Forall_Filter_Amount_Decimal f
830 , jump [ "C", "credit" ] filter_amount_operator $ do
831 f <- filter_amount Filter_Polarized_Negative
833 Bool $ Forall_Filter_GL_Decimal $
835 get_Forall_Filter_Amount_Decimal f
836 , jump [ "B", "balance" ] filter_amount_operator $ do
837 f <- filter_amount Filter_Polarized_Sum
839 Bool $ Forall_Filter_GL_Decimal $
841 get_Forall_Filter_Amount_Decimal f
842 , jump [ "RD", "running-debit" ] filter_amount_operator $ do
843 f <- filter_amount Filter_Polarized_Positive
845 Bool $ Forall_Filter_GL_Decimal $
847 get_Forall_Filter_Amount_Decimal f
848 , jump [ "RC", "running-credit" ] filter_amount_operator $ do
849 f <- filter_amount Filter_Polarized_Negative
851 Bool $ Forall_Filter_GL_Decimal $
853 get_Forall_Filter_Amount_Decimal f
854 , jump [ "RB", "running-balance" ] filter_amount_operator $ do
855 f <- filter_amount Filter_Polarized_Sum
857 Bool $ Forall_Filter_GL_Decimal $
859 get_Forall_Filter_Amount_Decimal f
863 Bool $ Forall_Filter_GL_Decimal $
865 get_Forall_Filter_Account <$> f