{-|
This module contains a collection of orderings of dubious utility, inspired by <http://haskell.1045720.n5.nabble.com/A-Down-newtype-in-Data-Ord-td5005373.html this> discussion on the haskell-cafe mailing-list.
-}

module Acme.MiscOrder (
      Contrarian(..),
      LuckySortOrder(..),
      Perverse(..),
      Fiendish(..)
) where

import Control.Monad
import System.Random
import System.IO.Unsafe(unsafePerformIO)

reverseOrdering :: Ordering -> Ordering
reverseOrdering LT = GT
reverseOrdering EQ = EQ
reverseOrdering GT = LT

-- | This newtype inverts the result of the (==) function.
newtype Contrarian a = Contrarian a

instance Eq a => Eq (Contrarian a) where
    (==) (Contrarian x) (Contrarian y) = (/=) x y

-- | This newtype is perfect to transform any sorting algorithm into a lucky sort!
newtype LuckySortOrder a = LuckySortOrder a deriving (Eq)

instance Ord a => Ord (LuckySortOrder a) where
    (<=) (LuckySortOrder x) (LuckySortOrder y) = True

{-| 
This newtype gives a random result for any two inequal values.
A warning though: given that I didn't manage to memoize a polymorphic function for use as a typeclass instance, its Ord instance can give different results on different calls with the same arguments.
-}
newtype Fiendish a = Fiendish a deriving (Eq, Show)

instance Eq a => Ord (Fiendish a) where
    compare x y
      | x == y = EQ
      | unsafePerformIO randomIO = LT
      | otherwise = GT


-- | This newtype does respects the equality relation laws…by treating any two values as equal
newtype Perverse a = Perverse a

instance Eq (Perverse a) where
    (==) _ _ = True

instance Ord (Perverse a) where
    compare _ _ = EQ