1 {-# LANGUAGE DeriveTraversable #-}
2 module Distribution
.Solver
.Modular
.PSQ
3 ( PSQ
(..) -- Unit test needs constructor access
31 -- Priority search queues.
33 -- I am not yet sure what exactly is needed. But we need a data structure with
34 -- key-based lookup that can be sorted. We're using a sequence right now with
35 -- (inefficiently implemented) lookup, because I think that queue-based
36 -- operations and sorting turn out to be more efficiency-critical in practice.
38 import Control
.Arrow
(first
, second
)
40 import qualified Data
.Foldable
as F
42 import qualified Data
.List
as S
43 import Data
.Ord
(comparing
)
44 import Data
.Traversable
45 import Prelude
hiding (foldr, length, lookup, filter, null, map)
47 newtype PSQ k v
= PSQ
[(k
, v
)]
48 deriving (Eq
, Show, Functor
, F
.Foldable
, Traversable
) -- Qualified Foldable to avoid issues with FTP
50 keys
:: PSQ k v
-> [k
]
51 keys
(PSQ xs
) = fmap fst xs
53 lookup :: Eq k
=> k
-> PSQ k v
-> Maybe v
54 lookup k
(PSQ xs
) = S
.lookup k xs
56 map :: (v1
-> v2
) -> PSQ k v1
-> PSQ k v2
57 map f
(PSQ xs
) = PSQ
(fmap (second f
) xs
)
59 mapKeys
:: (k1
-> k2
) -> PSQ k1 v
-> PSQ k2 v
60 mapKeys f
(PSQ xs
) = PSQ
(fmap (first f
) xs
)
62 mapWithKey
:: (k
-> a
-> b
) -> PSQ k a
-> PSQ k b
63 mapWithKey f
(PSQ xs
) = PSQ
(fmap (\ (k
, v
) -> (k
, f k v
)) xs
)
65 fromList
:: [(k
, a
)] -> PSQ k a
68 cons
:: k
-> a
-> PSQ k a
-> PSQ k a
69 cons k x
(PSQ xs
) = PSQ
((k
, x
) : xs
)
71 snoc
:: PSQ k a
-> k
-> a
-> PSQ k a
72 snoc
(PSQ xs
) k x
= PSQ
(xs
++ [(k
, x
)])
74 casePSQ
:: PSQ k a
-> r
-> (k
-> a
-> PSQ k a
-> r
) -> r
75 casePSQ
(PSQ xs
) n c
=
78 (k
, v
) : ys
-> c k v
(PSQ ys
)
80 sortBy :: (a
-> a
-> Ordering) -> PSQ k a
-> PSQ k a
81 sortBy cmp
(PSQ xs
) = PSQ
(S
.sortBy (cmp `on`
snd) xs
)
83 sortByKeys
:: (k
-> k
-> Ordering) -> PSQ k a
-> PSQ k a
84 sortByKeys cmp
(PSQ xs
) = PSQ
(S
.sortBy (cmp `on`
fst) xs
)
86 maximumBy :: (k
-> Int) -> PSQ k a
-> (k
, a
)
87 maximumBy sel
(PSQ xs
) =
88 S
.minimumBy (flip (comparing
(sel
. fst))) xs
90 minimumBy :: (a
-> Int) -> PSQ k a
-> PSQ k a
91 minimumBy sel
(PSQ xs
) =
92 PSQ
[snd (S
.minimumBy (comparing
fst) (S
.map (\ x
-> (sel
(snd x
), x
)) xs
))]
94 -- | Sort the list so that values satisfying the predicate are first.
95 prefer
:: (a
-> Bool) -> PSQ k a
-> PSQ k a
96 prefer p
= sortBy $ flip (comparing p
)
98 -- | Sort the list so that keys satisfying the predicate are first.
99 preferByKeys
:: (k
-> Bool) -> PSQ k a
-> PSQ k a
100 preferByKeys p
= sortByKeys
$ flip (comparing p
)
102 -- | Will partition the list according to the predicate. If
103 -- there is any element that satisfies the predicate, then only
104 -- the elements satisfying the predicate are returned.
105 -- Otherwise, the rest is returned.
107 filterIfAny
:: (a
-> Bool) -> PSQ k a
-> PSQ k a
108 filterIfAny p
(PSQ xs
) =
110 (pro
, con
) = S
.partition (p
. snd) xs
112 if S
.null pro
then PSQ con
else PSQ pro
114 -- | Variant of 'filterIfAny' that takes a predicate on the keys
115 -- rather than on the values.
117 filterIfAnyByKeys
:: (k
-> Bool) -> PSQ k a
-> PSQ k a
118 filterIfAnyByKeys p
(PSQ xs
) =
120 (pro
, con
) = S
.partition (p
. fst) xs
122 if S
.null pro
then PSQ con
else PSQ pro
124 filterKeys
:: (k
-> Bool) -> PSQ k a
-> PSQ k a
125 filterKeys p
(PSQ xs
) = PSQ
(S
.filter (p
. fst) xs
)
127 filter :: (a
-> Bool) -> PSQ k a
-> PSQ k a
128 filter p
(PSQ xs
) = PSQ
(S
.filter (p
. snd) xs
)
130 length :: PSQ k a
-> Int
131 length (PSQ xs
) = S
.length xs
133 null :: PSQ k a
-> Bool
134 null (PSQ xs
) = S
.null xs
136 isZeroOrOne
:: PSQ k a
-> Bool
137 isZeroOrOne
(PSQ
[]) = True
138 isZeroOrOne
(PSQ
[_
]) = True
139 isZeroOrOne _
= False
141 firstOnly
:: PSQ k a
-> PSQ k a
142 firstOnly
(PSQ
[]) = PSQ
[]
143 firstOnly
(PSQ
(x
: _
)) = PSQ
[x
]
145 toList
:: PSQ k a
-> [(k
, a
)]
148 union :: PSQ k a
-> PSQ k a
-> PSQ k a
149 union (PSQ xs
) (PSQ ys
) = PSQ
(xs
++ ys
)