module Data.PartialOrd
( PartialOrd(..)
, maxima, minima
, elem, notElem
, nub ) where
import Data.Bool
import Data.Maybe
import Prelude (Int, Integer, Float, Double, ($), Integral)
import qualified Data.Ord as Ord
import qualified Data.Eq as Eq
import qualified Data.List as List
import qualified Data.Set as Set
import qualified Data.Foldable as Foldable
class PartialOrd a where
(<=) :: a -> a -> Bool
(>=) :: a -> a -> Bool
a >= a' = a' <= a
(==) :: a -> a -> Bool
a == a' = a <= a' && a' <= a
(/=) :: a -> a -> Bool
a /= a' = not (a == a')
(<) :: a -> a -> Bool
a < a' = a <= a' && (a /= a')
(>) :: a -> a -> Bool
a > a' = a' <= a && (a /= a')
compare :: a -> a -> Maybe Ord.Ordering
compare a a' = if | a == a' -> Just Ord.EQ
| a <= a' -> Just Ord.LT
| a >= a' -> Just Ord.GT
| otherwise -> Nothing
instance PartialOrd Int where
(<=) = (Ord.<=)
instance PartialOrd Integer where
(<=) = (Ord.<=)
instance PartialOrd Double where
(<=) = (Ord.<=)
instance PartialOrd Float where
(<=) = (Ord.<=)
instance (Ord.Ord a) => PartialOrd (Set.Set a) where
(<=) = Set.isSubsetOf
instance PartialOrd a => PartialOrd [a] where
(<=) = isSublistOf
isSublistOf :: PartialOrd a => [a] -> [a] -> Bool
isSublistOf [] _ = True
isSublistOf (a:as) a' = a `elem` a' && as `isSublistOf` a'
maxima :: PartialOrd a => [a] -> [a]
maxima as = nub $ extrema (<=) as
minima :: PartialOrd a => [a] -> [a]
minima as = nub $ extrema (>=) as
extrema :: PartialOrd a => (a -> a -> Bool) -> [a] -> [a]
extrema f as = List.filter isExtremal as
where isExtremal a =
let as' = List.filter (/= a) as
in not (Foldable.any (a `f`) as')
elem :: (PartialOrd a, Foldable.Foldable t) => a -> t a -> Bool
elem x xs = Foldable.any (x ==) xs
notElem :: (PartialOrd a, Foldable.Foldable t) => a -> t a -> Bool
notElem x xs = not $ elem x xs
nub :: PartialOrd a => [a] -> [a]
nub as = List.reverse $ Foldable.foldl' collect [] as
where collect uniques a =
if a `elem` uniques
then uniques
else a : uniques