1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE MultiParamTypeClasses #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
6 module Hcompta.Tag where
8 import Control.Arrow (second)
9 import Control.Applicative (Applicative(..))
10 import Control.DeepSeq (NFData(..))
13 import Data.Function (flip)
14 import Data.Functor (Functor(..))
15 import Data.List.NonEmpty (NonEmpty(..))
16 import qualified Data.List.NonEmpty as NonEmpty
17 import Data.Map.Strict (Map)
18 import qualified Data.Map.Strict as Data.Map
19 import Data.Maybe (Maybe(..))
20 import Data.Monoid (Monoid(..))
21 import Data.Text (Text)
22 import qualified Data.Text as Text
23 import Data.Typeable ()
24 import Prelude (($), (.), Int)
25 import Text.Show (Show)
27 import Hcompta.Lib.Consable
31 -- | An 'Tag' is a non-empty list of 'Section'.
32 type Tag = (Path, Value)
34 type Path = NonEmpty Section
37 = Tags (Map Path [Value])
38 deriving (Data, Eq, Show, Typeable)
39 unTags :: Tags -> Map Path [Value]
42 instance Monoid Tags where
44 mappend (Tags x0) (Tags x1) =
45 Tags (Data.Map.unionWith mappend x0 x1)
46 instance Consable Tag Tags where
48 instance NFData Tags where
51 -- | Return the given 'Tags' with the given 'Tag' incorporated.
52 cons :: Tag -> Tags -> Tags
53 cons (p, v) (Tags xs) = Tags $ mcons (p, [v]) xs
55 -- | Return the 'Tag' formed by the given 'Path' and 'Value'.
56 tag :: Path -> Value -> Tag
59 -- | Return the 'Value' formed by the given 'Section' and 'Section's.
60 path :: Section -> [Section] -> Path
63 -- | Return the 'Value' of a 'Tag', if any.
64 value :: Tag -> Maybe Value
65 value (_, v) | Text.null v = Nothing
68 -- | Return the number of 'Section's in the given 'Tag'.
70 depth = NonEmpty.length
72 -- | Return a 'Path' from the given list.
73 from_List :: [(Path, Value)] -> Tags
74 from_List = Tags . Data.Map.fromListWith (flip mappend) . fmap (second pure)