{-# LANGUAGE BangPatterns, CPP, NoImplicitPrelude, PackageImports #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif

-- |
-- The Haskell 98 Prelude: a standard module imported by default
-- into all Haskell modules.  For more documentation, see the Haskell 98
-- Report <http://www.haskell.org/onlinereport/>.

module Prelude (

        -- * Standard types, classes and related functions

        -- ** Basic data types
        Bool(False, True),
        (&&), (||), not, otherwise,

        Maybe(Nothing, Just),
        maybe,

        Either(Left, Right),
        either,

        Ordering(LT, EQ, GT),
        Char, String,

        -- *** Tuples
        fst, snd, curry, uncurry,

#ifdef __HUGS__
        (:),                -- Not legal Haskell 98
#endif

        -- ** Basic type classes
        Eq((==), (/=)),
        Ord(compare, (<), (<=), (>=), (>), max, min),
        Enum(succ, pred, toEnum, fromEnum, enumFrom, enumFromThen,
             enumFromTo, enumFromThenTo),
        Bounded(minBound, maxBound),

        -- ** Numbers

        -- *** Numeric types
        Int, Integer, Float, Double,
        Rational,

        -- *** Numeric type classes
        Num((+), (-), (*), negate, abs, signum, fromInteger),
        Real(toRational),
        Integral(quot, rem, div, mod, quotRem, divMod, toInteger),
        Fractional((/), recip, fromRational),
        Floating(pi, exp, log, sqrt, (**), logBase, sin, cos, tan,
                 asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh),
        RealFrac(properFraction, truncate, round, ceiling, floor),
        RealFloat(floatRadix, floatDigits, floatRange, decodeFloat,
                  encodeFloat, exponent, significand, scaleFloat, isNaN,
                  isInfinite, isDenormalized, isIEEE, isNegativeZero, atan2),

        -- *** Numeric functions
        subtract, even, odd, gcd, lcm, (^), (^^),
        fromIntegral, realToFrac,

        -- ** Monads and functors
        Monad((>>=), (>>), return, fail),
        Functor(fmap),
        mapM, mapM_, sequence, sequence_, (=<<),

        -- ** Miscellaneous functions
        id, const, (.), flip, ($), until,
        asTypeOf, error, undefined,
        seq, ($!),

        -- * List operations
        map, (++), filter,
        head, last, tail, init, null, length, (!!),
        reverse,
        -- ** Reducing lists (folds)
        foldl, foldl1, foldr, foldr1,
        -- *** Special folds
        and, or, any, all,
        sum, product,
        concat, concatMap,
        maximum, minimum,
        -- ** Building lists
        -- *** Scans
        scanl, scanl1, scanr, scanr1,
        -- *** Infinite lists
        iterate, repeat, replicate, cycle,
        -- ** Sublists
        take, drop, splitAt, takeWhile, dropWhile, span, break,
        -- ** Searching lists
        elem, notElem, lookup,
        -- ** Zipping and unzipping lists
        zip, zip3, zipWith, zipWith3, unzip, unzip3,
        -- ** Functions on strings
        lines, words, unlines, unwords,

        -- * Converting to and from @String@
        -- ** Converting to @String@
        ShowS,
        Show(showsPrec, showList, show),
        shows,
        showChar, showString, showParen,
        -- ** Converting from @String@
        ReadS,
        Read(readsPrec, readList),
        reads, readParen, read, lex,

        -- * Basic Input and output
        IO,
        -- ** Simple I\/O operations
        -- All I/O functions defined here are character oriented.  The
        -- treatment of the newline character will vary on different systems.
        -- For example, two characters of input, return and linefeed, may
        -- read as a single newline character.  These functions cannot be
        -- used portably for binary I/O.
        -- *** Output functions
        putChar,
        putStr, putStrLn, print,
        -- *** Input functions
        getChar,
        getLine, getContents, interact,
        -- *** Files
        FilePath,
        readFile, writeFile, appendFile, readIO, readLn,
        -- ** Exception handling in the I\/O monad
        IOError, ioError, userError, catch

    ) where

#ifndef __HUGS__
import qualified "base" Control.Exception.Base as New (catch)
import "base" Control.Monad
import "base" System.IO
import "base" System.IO.Error (IOError, ioError, userError)
import "base" Data.List hiding ( splitAt )
import "base" Data.Either
import "base" Data.Maybe
import "base" Data.Tuple
#endif

#ifdef __GLASGOW_HASKELL__
import GHC.Base
-- import GHC.IO
-- import GHC.IO.Exception
import Text.Read
import GHC.Enum
import GHC.Num
import GHC.Real hiding ( gcd )
import qualified GHC.Real ( gcd )
import GHC.Float
import GHC.Show
#endif

#ifdef __HUGS__
import Hugs.Prelude
#endif

#ifndef __HUGS__
infixr 0 $!
#endif

-- -----------------------------------------------------------------------------
-- Miscellaneous functions

-- | Strict (call-by-value) application, defined in terms of 'seq'.
($!)    :: (a -> b) -> a -> b
#ifdef __GLASGOW_HASKELL__
f $! x  = let !vx = x in f vx  -- see #2273
#elif !defined(__HUGS__)
f $! x  = x `seq` f x
#endif

#ifdef __HADDOCK__
-- | The value of @'seq' a b@ is bottom if @a@ is bottom, and otherwise
-- equal to @b@.  'seq' is usually introduced to improve performance by
-- avoiding unneeded laziness.
seq :: a -> b -> b
seq _ y = y
#endif

-- | The 'catch' function establishes a handler that receives any
-- 'IOError' raised in the action protected by 'catch'.
-- An 'IOError' is caught by
-- the most recent handler established by one of the exception handling
-- functions.  These handlers are
-- not selective: all 'IOError's are caught.  Exception propagation
-- must be explicitly provided in a handler by re-raising any unwanted
-- exceptions.  For example, in
--
-- > f = catch g (\e -> if IO.isEOFError e then return [] else ioError e)
--
-- the function @f@ returns @[]@ when an end-of-file exception
-- (cf. 'System.IO.Error.isEOFError') occurs in @g@; otherwise, the
-- exception is propagated to the next outer handler.
--
-- When an exception propagates outside the main program, the Haskell
-- system prints the associated 'IOError' value and exits the program.
--
-- Non-I\/O exceptions are not caught by this variant; to catch all
-- exceptions, use 'Control.Exception.catch' from "Control.Exception".
catch :: IO a -> (IOError -> IO a) -> IO a
catch = New.catch

#ifdef __GLASGOW_HASKELL__
-- | @'gcd' x y@ is the greatest (positive) integer that divides both @x@
-- and @y@; for example @'gcd' (-3) 6@ = @3@, @'gcd' (-3) (-6)@ = @3@,
-- @'gcd' 0 4@ = @4@.  @'gcd' 0 0@ raises a runtime error.
gcd             :: (Integral a) => a -> a -> a
gcd 0 0         =  error "Prelude.gcd: gcd 0 0 is undefined"
gcd x y         = GHC.Real.gcd x y
#endif

#ifndef __HUGS__
-- The GHC's version of 'splitAt' is too strict in 'n' compared to
-- Haskell98/2010 version. Ticket #1182.

-- | 'splitAt' @n xs@ returns a tuple where first element is @xs@ prefix of
-- length @n@ and second element is the remainder of the list:
--
-- > splitAt 6 "Hello World!" == ("Hello ","World!")
-- > splitAt 3 [1,2,3,4,5] == ([1,2,3],[4,5])
-- > splitAt 1 [1,2,3] == ([1],[2,3])
-- > splitAt 3 [1,2,3] == ([1,2,3],[])
-- > splitAt 4 [1,2,3] == ([1,2,3],[])
-- > splitAt 0 [1,2,3] == ([],[1,2,3])
-- > splitAt (-1) [1,2,3] == ([],[1,2,3])
--
-- It is equivalent to @('take' n xs, 'drop' n xs)@.
-- 'splitAt' is an instance of the more general 'Data.List.genericSplitAt',
-- in which @n@ may be of any integral type.
splitAt                :: Int -> [a] -> ([a],[a])
splitAt n xs           =  (take n xs, drop n xs)
#endif
