1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE MultiParamTypeClasses #-}
4 {-# LANGUAGE TypeFamilies #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
6 module Hcompta.Tag where
8 import Control.Applicative (Applicative(..))
9 import Control.Arrow (second)
10 import Control.DeepSeq (NFData(..))
13 import Data.Function (($), (.), flip)
14 import Data.Functor (Functor(..))
16 import Data.Map.Strict (Map)
17 import qualified Data.Map.Strict as Map
18 import Data.Proxy (Proxy(..))
19 import Data.Maybe (Maybe(..))
20 import Data.Monoid (Monoid(..))
21 import qualified Data.Sequences as Seqs
22 import Data.NonNull (NonNull)
23 import Data.Text (Text)
24 import qualified Data.Text as Text
25 import Data.Tuple (fst, snd)
26 import Data.Typeable ()
27 import Text.Show (Show)
28 import qualified Data.MonoTraversable as MT
30 import Hcompta.Lib.Consable
33 -- import Language.Symantic as Sym
49 class Tag (MT.Element ts) => Tags ts
55 tag_path :: t -> Tag_Path t
56 tag_value :: t -> Tag_Value t
57 instance Tag (path, value) where
58 type Tag_Path (path, value) = path
59 type Tag_Value (path, value) = value
64 class Tag (Tags_Tag ts) => Tags ts where
72 Tags (Map path ts) where
73 type Tags_Tag (Map path ts) = Tags_Tag ts
77 class Tags (Tags_Of a) => Tags_of a where
79 tags_of :: a -> Tags_Of a
85 -- | An 'Tag' is a non-empty list of 'Tag_Section'.
86 type Tag = (Tag_Path, Tag_Value)
87 type Tag_Path = NonNull [Tag_Section]
88 type Tag_Section = Name
93 = Tags (Map Tag_Path [Tag_Value])
94 deriving (Data, Eq, NFData, Show, Typeable
95 , MT.MonoFunctor, MT.MonoFoldable)
96 unTags :: Tags -> Map Tag_Path [Tag_Value]
102 instance Monoid Tags where
104 mappend (Tags x) (Tags y) =
105 Tags (Map.unionWith (flip mappend) x y)
106 instance Consable Tag Tags where
108 instance NFData Tags where
110 -- | Return the given 'Tags' with the given 'Tag' incorporated.
111 tag_cons :: Tag -> Tags -> Tags
112 tag_cons (p, v) (Tags xs) = Tags $ mcons (p, [v]) xs
114 -- | Return the 'Tag' formed by the given 'Tag_Path' and 'Tag_Value'.
115 tag :: Tag_Path -> Tag_Value -> Tag
118 -- | Return the 'Tag_Value' formed by the given 'Tag_Section' and 'Tag_Section's.
119 tag_path :: Tag_Section -> [Tag_Section] -> Tag_Path
122 -- | Return the 'Tag_Value' of a 'Tag', if any.
123 tag_value :: Tag -> Maybe Tag_Value
124 tag_value (_, v) | Text.null v = Nothing
125 tag_value (_, v) = Just v
127 -- | Return the number of 'Tag_Section's in the given 'Tag'.
128 tag_depth :: Tag_Path -> Int
129 tag_depth = NonEmpty.length
131 -- | Return a 'Tag_Path' from the given list.
132 tag_from_List :: [(Tag_Path, Tag_Value)] -> Tags
133 tag_from_List = Tags . Map.fromListWith (flip mappend) . fmap (second pure)