    {-# OPTIONS_GHC -XNoImplicitPrelude #-}
    {-# OPTIONS_HADDOCK hide #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Classes
    -- Copyright   :  (c) The University of Glasgow, 1992-2002
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  cvs-ghc@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC extensions)
    --
    -- Basic classes.
    --
    -----------------------------------------------------------------------------

    module GHC.Classes where

    import GHC.Bool
    import GHC.Ordering

    infix  4  ==, /=, <, <=, >=, >
    infixr 3  &&
    infixr 2  ||

    default ()              -- Double isn't available yet

    -- | The 'Eq' class defines equality ('==') and inequality ('/=').
    -- All the basic datatypes exported by the "Prelude" are instances of 'Eq',
    -- and 'Eq' may be derived for any datatype whose constituents are also
    -- instances of 'Eq'.
    --
    -- Minimal complete definition: either '==' or '/='.
    --
    class  Eq a  where
        (==), (/=)           :: a -> a -> Bool

        x /= y               = not (x == y)
        x == y               = not (x /= y)

    -- | The 'Ord' class is used for totally ordered datatypes.
    --
    -- Instances of 'Ord' can be derived for any user-defined
    -- datatype whose constituent types are in 'Ord'.  The declared order
    -- of the constructors in the data declaration determines the ordering
    -- in derived 'Ord' instances.  The 'Ordering' datatype allows a single
    -- comparison to determine the precise ordering of two objects.
    --
    -- Minimal complete definition: either 'compare' or '<='.
    -- Using 'compare' can be more efficient for complex types.
    --
    class  (Eq a) => Ord a  where
        compare              :: a -> a -> Ordering
        (<), (<=), (>), (>=) :: a -> a -> Bool
        max, min             :: a -> a -> a

        compare x y = if x == y then EQ
                      -- NB: must be '<=' not '<' to validate the
                      -- above claim about the minimal things that
                      -- can be defined for an instance of Ord:
                      else if x <= y then LT
                      else GT

        x <  y = case compare x y of { LT -> True;  _ -> False }
        x <= y = case compare x y of { GT -> False; _ -> True }
        x >  y = case compare x y of { GT -> True;  _ -> False }
        x >= y = case compare x y of { LT -> False; _ -> True }

            -- These two default methods use '<=' rather than 'compare'
            -- because the latter is often more expensive
        max x y = if x <= y then y else x
        min x y = if x <= y then x else y

    -- OK, so they're technically not part of a class...:

    -- Boolean functions

    -- | Boolean \"and\"
    (&&)                    :: Bool -> Bool -> Bool
    True  && x              =  x
    False && _              =  False

    -- | Boolean \"or\"
    (||)                    :: Bool -> Bool -> Bool
    True  || _              =  True
    False || x              =  x

    -- | Boolean \"not\"
    not                     :: Bool -> Bool
    not True                =  False
    not False               =  True