1 {-# LANGUAGE DeriveAnyClass #-}
3 module Literate.Accounting.Flow where
7 import Data.Functor (Functor)
8 import Data.Maybe (Maybe (..))
9 import Data.Ord (Ord (..))
10 import GHC.Generics (Generic)
11 import Text.Show (Show (..))
13 import Literate.Accounting.Quantity
14 import Literate.Prelude
18 -- | A 'Flow keeps track separatly of what 'FlowSource'
19 -- and what 'FlowDest' of an account.
24 deriving (Eq, Show, Generic, NFData, Functor)
26 instance FromInteger qty => FromInteger (Flow qty) where
28 | i <= 0 = FlowDest (fromInteger i)
29 | otherwise = FlowSource (fromInteger i)
30 instance (Zeroable a, Addable a) => Zeroable (Flow a) where
31 zero = FlowSource zero
33 FlowDest o -> isZero o
34 FlowSource i -> isZero i
35 FlowBidir o i -> isZero (o + i)
36 instance Addable a => Addable (Flow a) where
37 FlowSource i + FlowDest o = FlowBidir o i
38 FlowSource ix + FlowSource py = FlowSource (ix + py)
39 FlowSource i + FlowBidir ny py = FlowBidir ny (i + py)
40 FlowDest ox + FlowDest ny = FlowDest (ox + ny)
41 FlowDest o + FlowSource i = FlowBidir o i
42 FlowDest ox + FlowBidir ny i = FlowBidir (ox + ny) i
43 FlowBidir ox ix + FlowDest o = FlowBidir (ox + o) ix
44 FlowBidir ox ix + FlowSource py = FlowBidir ox (ix + py)
45 FlowBidir ox ix + FlowBidir ny py = FlowBidir (ox + ny) (ix + py)
46 instance Flowable (Flow a) where
48 FlowSource _ -> Nothing
50 FlowBidir n _ -> Just (FlowDest n)
52 FlowSource _ -> Just f
54 FlowBidir _ p -> Just (FlowSource p)
56 flowIn :: Flow a -> Maybe a
58 FlowSource i -> Just i
60 FlowBidir _ i -> Just i
62 flowOut :: Flow a -> Maybe a
64 FlowSource _ -> Nothing
66 FlowBidir o _ -> Just o
68 flow :: Flowable a => a -> Flow a
70 case (outOf f, inOf f) of
71 (Just o, Nothing) -> FlowDest o
72 (Nothing, Just i) -> FlowSource i
73 (Just o, Just i) -> FlowBidir o i
74 (Nothing, Nothing) -> FlowBidir f f
75 unFlow :: Addable a => Flow a -> a
79 FlowBidir o i -> o + i
82 class Flowable a where
87 instance Flowable Decimal where
96 instance Flowable a => Flowable (Map k a) where
98 case Map.mapMaybe inOf q of
99 m | Map.null m -> Nothing
102 case Map.mapMaybe outOf q of
103 m | Map.null m -> Nothing
105 instance Flowable a => Flowable (k, a) where
106 inOf (u, q) = (u,) <$> inOf q
107 outOf (u, q) = (u,) <$> outOf q