    module Numeric.Order.Class
      ( Order(..)
      , orderOrd
      ) where

    import Data.Int
    import Data.Word
    import Data.Set
    import Numeric.Natural.Internal

    -- a partial order (a, <=)
    class Order a where
      (<~) :: a -> a -> Bool
      a <~ b = maybe False (<= EQ) (order a b)

      (<) :: a -> a -> Bool
      a < b = order a b == Just LT

      (>~) :: a -> a -> Bool
      a >~ b = b <~ a

      (>) :: a -> a -> Bool
      a > b = order a b == Just GT

      (~~) :: a -> a -> Bool
      a ~~ b = order a b == Just EQ

      (/~) :: a -> a -> Bool
      a /~ b = order a b /= Just EQ

      order :: a -> a -> Maybe Ordering
      order a b
        | a <~ b = Just $ if b <~ a
                   then EQ
                   else LT
        | b <~ a = Just GT
        | otherwise = Nothing

      comparable :: a -> a -> Bool
      comparable a b = maybe False (const True) (order a b)

    orderOrd :: Ord a => a -> a -> Maybe Ordering
    orderOrd a b = Just (compare a b)

    instance Order Bool where order = orderOrd
    instance Order Integer where order = orderOrd
    instance Order Int where order = orderOrd
    instance Order Int8 where order = orderOrd
    instance Order Int16 where order = orderOrd
    instance Order Int32 where order = orderOrd
    instance Order Int64 where order = orderOrd
    instance Order Natural where order = orderOrd
    instance Order Word where order = orderOrd
    instance Order Word8 where order = orderOrd
    instance Order Word16 where order = orderOrd
    instance Order Word32 where order = orderOrd
    instance Order Word64 where order = orderOrd
    instance Ord a => Order (Set a) where
      (<~) = isSubsetOf

    instance Order () where
      order _ _ = Just EQ
      _ <~ _ = True
      comparable _ _ = True

    instance (Order a, Order b) => Order (a, b) where
      (a,b) <~ (i,j) = a <~ i && b <~ j

    instance (Order a, Order b, Order c) => Order (a, b, c) where
      (a,b,c) <~ (i,j,k) = a <~ i && b <~ j && c <~ k

    instance (Order a, Order b, Order c, Order d) => Order (a, b, c, d) where
      (a,b,c,d) <~ (i,j,k,l) = a <~ i && b <~ j && c <~ k && d <~ l

    instance (Order a, Order b, Order c, Order d, Order e) => Order (a, b, c, d, e) where
      (a,b,c,d,e) <~ (i,j,k,l,m) = a <~ i && b <~ j && c <~ k && d <~ l && e <~ m