summaryrefslogtreecommitdiff
path: root/lib/Postdelay/PrioMap.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Postdelay/PrioMap.hs')
-rw-r--r--lib/Postdelay/PrioMap.hs70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/Postdelay/PrioMap.hs b/lib/Postdelay/PrioMap.hs
new file mode 100644
index 0000000..2b75984
--- /dev/null
+++ b/lib/Postdelay/PrioMap.hs
@@ -0,0 +1,70 @@
1{-# LANGUAGE TemplateHaskell, ViewPatterns, RankNTypes, GeneralizedNewtypeDeriving, DeriveTraversable, ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses #-}
2
3module Postdelay.PrioMap
4 ( PrioMap, prioMap, prioMap', _Endo
5 , prio, prios
6 , squash
7
8 , PrioEndo, prioEndo, prioEndo'
9 ) where
10
11import Data.IntMap.Strict (IntMap)
12import qualified Data.IntMap.Strict as IntMap
13
14import Control.Lens
15
16import Data.Foldable
17import Data.Semigroup
18
19
20makePrisms ''Endo
21
22newtype PrioMap p a = PrioMap (IntMap a)
23 deriving (Functor, Foldable, Traversable)
24makePrisms ''PrioMap
25
26instance Semigroup a => Semigroup (PrioMap p a) where
27 (PrioMap a) <> (PrioMap b) = PrioMap $ IntMap.unionWith (<>) a b
28
29instance Semigroup a => Monoid (PrioMap p a) where
30 mempty = PrioMap mempty
31 mappend = (<>)
32
33instance Enum p => FunctorWithIndex p (PrioMap p) where
34 imap f (PrioMap intMap) = PrioMap $ imap (f . toEnum) intMap
35
36instance Enum p => FoldableWithIndex p (PrioMap p) where
37 ifoldMap f (PrioMap intMap) = ifoldMap (f . toEnum) intMap
38
39instance Enum p => TraversableWithIndex p (PrioMap p) where
40 itraverse f (PrioMap intMap) = PrioMap <$> itraverse (f . toEnum) intMap
41
42
43prioMap :: (Enum p, Monoid a) => Iso' (PrioMap p a) a
44-- ^ `prioMap` squashes priority information into `0`
45prioMap = prioMap' $ toEnum 0
46
47prioMap' :: (Enum p, Monoid a) => p -> Iso' (PrioMap p a) a
48-- ^ `prioMap' p` squashes priority information into `p`
49prioMap' (fromEnum -> p) = _PrioMap . iso fold (IntMap.singleton p)
50
51prio :: Enum p => p -> Lens' (PrioMap p a) (Maybe a)
52prio (fromEnum -> p) = _PrioMap . at p
53
54squash :: Semigroup a => PrioMap p (PrioMap p a) -> PrioMap p a
55squash = unwrapMonoid . foldMap WrapMonoid
56
57prios :: forall f p arr a. (Bounded p, Enum p, Semigroup a, Applicative f, Indexable p arr) => arr (Maybe a) (f (Maybe a)) -> (PrioMap p a -> f (PrioMap p a))
58prios (indexed -> alter) pMap = foldr cons_f (pure $ PrioMap IntMap.empty) [minBound .. maxBound]
59 where
60 cons_f :: p -> f (PrioMap p a) -> f (PrioMap p a)
61 cons_f p x = (<>) <$> (maybe mempty (PrioMap . IntMap.singleton (fromEnum p)) <$> alter p (pMap ^. prio p)) <*> x
62
63
64type PrioEndo p a = PrioMap p (Endo a)
65
66prioEndo :: Enum p => Iso' (PrioEndo p a) (Endo a)
67prioEndo = prioMap
68
69prioEndo' :: Enum p => p -> Iso' (PrioEndo p a) (Endo a)
70prioEndo' = prioMap'