content: {-# LANGUAGE RankNTypes, FlexibleInstances, FlexibleContexts, KindSignatures, ScopedTypeVariables, TemplateHaskell, ConstraintKinds #-}
  
  module Main where
  
  import           Data.Maybe
  import           Data.Typeable
  import           IfCxt
  import           Test.Tasty             (defaultMain, testGroup, localOption)
  import           Test.Tasty.QuickCheck
  
  mkIfCxtInstances ''Ord
  
  main = defaultMain $ testGroup "All tests" [
      testProperty      "Find Ord for Int"              findOrdInt
    , testProperty      "Find Ord for [Int]"            findOrdListInt
    , testProperty        "No Ord for (Int -> Int)" notFoundOrdFuncInt
    , testProperty        "No Ord for [Int -> Int]" notFoundOrdListFuncInt
    , testProperty       "Get Ord for Int"              haveOrdInt
    , testProperty       "Get Ord for [Int]"            haveOrdListInt
    , testProperty "Can't get Ord for (Int -> Int)"       noOrdFuncInt
    , testProperty "Can't get Ord for [Int -> Int]"       noOrdListFuncInt
    , testProperty   "Can use Ord for Int"            usableOrdInt
    , testProperty   "Can use Ord for [Int]"          usableOrdListInt
    , testProperty   "Can use Ord for (Int -> Int)" unusableOrdFuncInt
    , testProperty   "Can use Ord for [Int -> Int]" unusableOrdListFuncInt
    ]
  
  -- Tests
  
  findOrdInt             = ifCxt (Proxy :: Proxy (Ord Int))          True  False
  findOrdListInt         = ifCxt (Proxy :: Proxy (Ord [Int]))        True  False
  notFoundOrdFuncInt     = ifCxt (Proxy :: Proxy (Ord (Int -> Int))) False True
  notFoundOrdListFuncInt = ifCxt (Proxy :: Proxy (Ord [Int -> Int])) False True
  
  haveOrdInt       = isJust    $ getLTE (Proxy :: Proxy (Ord Int))
  haveOrdListInt   = isJust    $ getLTE (Proxy :: Proxy (Ord [Int]))
  noOrdFuncInt     = isNothing $ getLTE (Proxy :: Proxy (Ord (Int -> Int)))
  noOrdListFuncInt = isNothing $ getLTE (Proxy :: Proxy (Ord [Int -> Int]))
  
  usableOrdInt       (x :: Int)   y =   usableLTE x y
  usableOrdListInt   (x :: [Int]) y =   usableLTE x y
  unusableOrdFuncInt (x :: Int)   y = unusableLTE (+x) (*y)
  unusableOrdListFuncInt            = unusableLTE ([] :: [Int -> Int]) []
  
  -- Helpers
  
  getLTE :: forall proxy a. IfCxt (Ord a) => proxy (Ord a) -> Maybe (a -> a -> Bool)
  getLTE _ = ifCxt (Proxy :: Proxy (Ord a))
                   (Just (<=))
                   Nothing
  
  useLTE :: (IfCxt (Ord a)) => a -> a -> Maybe Bool
  useLTE x y = getLTE (Proxy :: Proxy (Ord a)) <*> pure x <*> pure y
  
  usableLTE :: (IfCxt (Ord a), Ord a) => a -> a -> Bool
  usableLTE x y = useLTE x y == Just (x <= y)
  
  unusableLTE :: (IfCxt (Ord a)) => a -> a -> Bool
  unusableLTE x y = useLTE x y == Nothing
  