{-
- Copyright (C) 2009 Nick Bowler.
-
- License BSD2: 2-clause BSD license. See LICENSE for full terms.
- This is free software: you are free to change and redistribute it.
- There is NO WARRANTY, to the extent permitted by law.
-}{-# LANGUAGE FlexibleInstances, OverlappingInstances, UndecidableInstances #-}moduleData.Poset.InternalwhereimportqualifiedData.ListasListimportqualifiedPreludeimportPreludehiding(Ordering(..),Ord(..))importData.MonoiddataOrdering=LT|EQ|GT|NCderiving(Eq,Show,Read,Bounded,Enum)-- Lexicographic ordering.instanceMonoidOrderingwheremempty=EQmappendEQx=xmappendNC_=NCmappendLT_=LTmappendGT_=GT-- | Internal-use function to convert our Ordering to the ordinary one.totalOrder::Ordering->Prelude.OrderingtotalOrderLT=Prelude.LTtotalOrderEQ=Prelude.EQtotalOrderGT=Prelude.GTtotalOrderNC=error"Uncomparable elements in total order."-- | Internal-use function to convert the ordinary Ordering to ours.partialOrder::Prelude.Ordering->OrderingpartialOrderPrelude.LT=LTpartialOrderPrelude.EQ=EQpartialOrderPrelude.GT=GT-- | Class for partially ordered data types. Instances should satisfy the-- following laws for all values a, b and c:---- * @a <= a@.---- * @a <= b@ and @b <= a@ implies @a == b@.---- * @a <= b@ and @b <= c@ implies @a <= c@.---- But note that the floating point instances don't satisfy the first rule.---- Minimal complete definition: 'compare' or '<='.classEqa=>Posetawherecompare::a->a->Ordering-- | Is comparable to.(<==>)::a->a->Bool-- | Is not comparable to.(</=>)::a->a->Bool(<)::a->a->Bool(<=)::a->a->Bool(>=)::a->a->Bool(>)::a->a->Boola`compare`b|a==b=EQ|a<=b=LT|b<=a=GT|otherwise=NCa<b=a`compare`b==LTa>b=a`compare`b==GTa<==>b=a`compare`b/=NCa</=>b=a`compare`b==NCa<=b=a<b||a`compare`b==EQa>=b=a>b||a`compare`b==EQ-- | Class for partially ordered data types where sorting makes sense.-- This includes all totally ordered sets and floating point types. Instances-- should satisfy the following laws:---- * The set of elements for which 'isOrdered' returns true is totally ordered.---- * The max (or min) of an insignificant element and a significant element-- is the significant one.---- * The result of sorting a list should contain only significant elements.---- * @max a b@ = @max b a@---- * @min a b@ = @min b a@---- The idea comes from floating point types, where non-comparable elements-- (NaNs) are the exception rather than the rule. For these types, we can-- define 'max', 'min' and 'sortBy' to ignore insignificant elements. Thus, a-- sort of floating point values will discard all NaNs and order the remaining-- elements.---- Minimal complete definition: 'isOrdered'classPoseta=>SortableawheresortBy::(a->a->Ordering)->[a]->[a]isOrdered::a->Boolmax::a->a->amin::a->a->asortByf=List.sortBy((totalOrder.).f).filterisOrderedmaxab=casea`compare`bofLT->bEQ->aGT->aNC->ifisOrderedathenaelseifisOrderedbthenbelseaminab=casea`compare`bofLT->aEQ->bGT->bNC->ifisOrderedathenaelseifisOrderedbthenbelsea-- | Class for totally ordered data types. Instances should satisfy-- @isOrdered a = True@ for all @a@.classSortablea=>Orda-- This hack allows us to leverage existing data structures defined in terms-- of 'Prelude.Ord'.instanceData.Poset.Internal.Orda=>Prelude.Ordawherecompare=(totalOrder.).compare(<)=(<)(<=)=(<=)(>=)=(>=)(>)=(>)min=minmax=max