diff options
Diffstat (limited to 'lib/Postdelay/PrioMap.hs')
| -rw-r--r-- | lib/Postdelay/PrioMap.hs | 70 |
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 | |||
| 3 | module Postdelay.PrioMap | ||
| 4 | ( PrioMap, prioMap, prioMap', _Endo | ||
| 5 | , prio, prios | ||
| 6 | , squash | ||
| 7 | |||
| 8 | , PrioEndo, prioEndo, prioEndo' | ||
| 9 | ) where | ||
| 10 | |||
| 11 | import Data.IntMap.Strict (IntMap) | ||
| 12 | import qualified Data.IntMap.Strict as IntMap | ||
| 13 | |||
| 14 | import Control.Lens | ||
| 15 | |||
| 16 | import Data.Foldable | ||
| 17 | import Data.Semigroup | ||
| 18 | |||
| 19 | |||
| 20 | makePrisms ''Endo | ||
| 21 | |||
| 22 | newtype PrioMap p a = PrioMap (IntMap a) | ||
| 23 | deriving (Functor, Foldable, Traversable) | ||
| 24 | makePrisms ''PrioMap | ||
| 25 | |||
| 26 | instance Semigroup a => Semigroup (PrioMap p a) where | ||
| 27 | (PrioMap a) <> (PrioMap b) = PrioMap $ IntMap.unionWith (<>) a b | ||
| 28 | |||
| 29 | instance Semigroup a => Monoid (PrioMap p a) where | ||
| 30 | mempty = PrioMap mempty | ||
| 31 | mappend = (<>) | ||
| 32 | |||
| 33 | instance Enum p => FunctorWithIndex p (PrioMap p) where | ||
| 34 | imap f (PrioMap intMap) = PrioMap $ imap (f . toEnum) intMap | ||
| 35 | |||
| 36 | instance Enum p => FoldableWithIndex p (PrioMap p) where | ||
| 37 | ifoldMap f (PrioMap intMap) = ifoldMap (f . toEnum) intMap | ||
| 38 | |||
| 39 | instance Enum p => TraversableWithIndex p (PrioMap p) where | ||
| 40 | itraverse f (PrioMap intMap) = PrioMap <$> itraverse (f . toEnum) intMap | ||
| 41 | |||
| 42 | |||
| 43 | prioMap :: (Enum p, Monoid a) => Iso' (PrioMap p a) a | ||
| 44 | -- ^ `prioMap` squashes priority information into `0` | ||
| 45 | prioMap = prioMap' $ toEnum 0 | ||
| 46 | |||
| 47 | prioMap' :: (Enum p, Monoid a) => p -> Iso' (PrioMap p a) a | ||
| 48 | -- ^ `prioMap' p` squashes priority information into `p` | ||
| 49 | prioMap' (fromEnum -> p) = _PrioMap . iso fold (IntMap.singleton p) | ||
| 50 | |||
| 51 | prio :: Enum p => p -> Lens' (PrioMap p a) (Maybe a) | ||
| 52 | prio (fromEnum -> p) = _PrioMap . at p | ||
| 53 | |||
| 54 | squash :: Semigroup a => PrioMap p (PrioMap p a) -> PrioMap p a | ||
| 55 | squash = unwrapMonoid . foldMap WrapMonoid | ||
| 56 | |||
| 57 | prios :: 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)) | ||
| 58 | prios (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 | |||
| 64 | type PrioEndo p a = PrioMap p (Endo a) | ||
| 65 | |||
| 66 | prioEndo :: Enum p => Iso' (PrioEndo p a) (Endo a) | ||
| 67 | prioEndo = prioMap | ||
| 68 | |||
| 69 | prioEndo' :: Enum p => p -> Iso' (PrioEndo p a) (Endo a) | ||
| 70 | prioEndo' = prioMap' | ||
