1 {-# LANGUAGE FlexibleInstances, OverlappingInstances, UndecidableInstances #-}
2 module Data
.Poset
.Internal
where
4 import qualified Data
.List
as List
5 import qualified Prelude
6 import Prelude
hiding (Ordering(..), Ord
(..))
10 data Ordering = LT | EQ | GT | NC
11 deriving (Eq
, Show, Read, Bounded
, Enum
)
13 -- Lexicographic ordering.
14 instance Monoid
Ordering where
21 -- | Internal-use function to convert our Ordering to the ordinary one.
22 totalOrder
:: Ordering -> Prelude
.Ordering
23 totalOrder LT
= Prelude
.LT
24 totalOrder EQ
= Prelude
.EQ
25 totalOrder GT
= Prelude
.GT
26 totalOrder NC
= error "Uncomparable elements in total order."
28 -- | Internal-use function to convert the ordinary Ordering to ours.
29 partialOrder
:: Prelude
.Ordering -> Ordering
30 partialOrder Prelude
.LT
= LT
31 partialOrder Prelude
.EQ
= EQ
32 partialOrder Prelude
.GT
= GT
34 -- | Class for partially ordered data types. Instances should satisfy the
35 -- following laws for all values a, b and c:
39 -- * @a <= b@ and @b <= a@ implies @a == b@.
41 -- * @a <= b@ and @b <= c@ implies @a <= c@.
43 -- But note that the floating point instances don't satisfy the first rule.
45 -- Minimal complete definition: 'compare' or '<='.
46 class Eq a
=> Poset a
where
47 compare :: a
-> a
-> Ordering
48 -- | Is comparable to.
49 (<==>) :: a
-> a
-> Bool
50 -- | Is not comparable to.
51 (</=>) :: a
-> a
-> Bool
53 (<=) :: a
-> a
-> Bool
54 (>=) :: a
-> a
-> Bool
63 a
< b
= a `
compare` b
== LT
64 a
> b
= a `
compare` b
== GT
65 a
<==> b
= a `
compare` b
/= NC
66 a
</=> b
= a `
compare` b
== NC
67 a
<= b
= a
< b || a `
compare` b
== EQ
68 a
>= b
= a
> b || a `
compare` b
== EQ
70 -- | Class for partially ordered data types where sorting makes sense.
71 -- This includes all totally ordered sets and floating point types. Instances
72 -- should satisfy the following laws:
74 -- * The set of elements for which 'isOrdered' returns true is totally ordered.
76 -- * The max (or min) of an insignificant element and a significant element
77 -- is the significant one.
79 -- * The result of sorting a list should contain only significant elements.
81 -- * @max a b@ = @max b a@
83 -- * @min a b@ = @min b a@
85 -- The idea comes from floating point types, where non-comparable elements
86 -- (NaNs) are the exception rather than the rule. For these types, we can
87 -- define 'max', 'min' and 'sortBy' to ignore insignificant elements. Thus, a
88 -- sort of floating point values will discard all NaNs and order the remaining
91 -- Minimal complete definition: 'isOrdered'
92 class Poset a
=> Sortable a
where
93 sortBy :: (a
-> a
-> Ordering) -> [a
] -> [a
]
94 isOrdered
:: a
-> Bool
98 sortBy f
= List
.sortBy ((totalOrder
.) . f
) . filter isOrdered
99 max a b
= case a `
compare` b
of
103 NC
-> if isOrdered a
then a
else if isOrdered b
then b
else a
104 min a b
= case a `
compare` b
of
108 NC
-> if isOrdered a
then a
else if isOrdered b
then b
else a
110 -- | Class for totally ordered data types. Instances should satisfy
111 -- @isOrdered a = True@ for all @a@.
112 class Sortable a
=> Ord a
114 -- This hack allows us to leverage existing data structures defined in terms
116 instance Data
.Poset
.Internal
.Ord a
=> Prelude
.Ord a
where
117 compare = (totalOrder
.) . compare