CurryInfo: base-3.3.0 / Prelude

classes:
Alternative Applicative Bounded Data Enum Eq Floating Fractional Functor Integral Monad MonadFail Monoid Num Ord Read Real RealFrac Show
documentation:
--------------------------------------------------------------------------------
--- The standard prelude of Curry with type classes.
--- All exported functions, data types, type classes
--- and methods defined in this module are always
--- available in any Curry program.
--------------------------------------------------------------------------------
name:
Prelude
operations:
!! $ $! $!! $# $## & && &> ++ . /== <$> =:<<= =:<= =:= =<< ? PEVAL ^ all and any anyOf ap appendFile apply asTypeOf break catch chr concat concatMap cond const constrEq curry doSolve drop dropWhile either elem ensureNotFree ensureSpine eqString error even failed filter flip foldl foldl1 foldr foldr1 fromIntegral fst getChar getLine groundNormalForm head id ifThenElse ioError isAlpha isAlphaNum isBinDigit isDigit isHexDigit isLower isOctDigit isSpace isUpper iterate length lex liftM2 lines lookup map mapM mapM_ maybe normalForm not notElem null odd or ord otherwise print putChar putStr putStrLn read readFile readParen reads realToFrac repeat replicate reverse seq sequence sequence_ showChar showParen showString showTuple shows snd solve span splitAt success tail take takeWhile uncurry unknown unlines until unwords unzip unzip3 userError words writeFile zip zip3 zipWith zipWith3 ||
sourcecode:
{-# LANGUAGE CPP #-}
{-# OPTIONS_FRONTEND -Wno-incomplete-patterns -Wno-overlapping #-}
{-# OPTIONS_FRONTEND --case-mode=free #-}

module Prelude
  (
  -- * Basic Datatypes
    Char (..), Int (..), Float (..)
--++   , () (..), (,) (..), (,,) (..), (,,,) (..), (,,,,) (..)
--++   , [] (..), (->) (..)
  , Bool (..), Ordering (..), Maybe (..), Either (..)

  -- * Type Classes
  , Data(..), (/==), Eq (..) , Ord (..)
  , Show (..), ShowS, shows, showChar, showString, showParen, showTuple
  , Read (..), ReadS, reads, readParen, read, lex
  , Bounded (..), Enum (..)
  -- ** Numerical Typeclasses
  , Num (..), Fractional (..), Real (..)
  , Integral (..), even, odd, fromIntegral, realToFrac, (^)
  , RealFrac (..), Floating (..), Monoid (..)
  -- Type Constructor Classes
  , Functor (..), Applicative (..), Alternative (..)
  , Monad (..), MonadFail(..)
  , (=<<), ap, liftM2, sequence, sequence_, mapM, mapM_

  -- * Operations on Characters
  , isUpper, isLower, isAlpha, isDigit, isAlphaNum
  , isBinDigit, isOctDigit, isHexDigit, isSpace
  , ord, chr
  , String, lines, unlines, words, unwords

  -- * Operations on Lists
  , head, tail, null, (++), length, (!!), map, foldl, foldl1, foldr, foldr1
  , filter, zip, zip3, zipWith, zipWith3, unzip, unzip3, concat, concatMap
  , iterate, repeat, replicate, take, drop, splitAt, takeWhile, dropWhile
  , span, break, reverse, and, or, any, all, elem, notElem, lookup, (<$>)

  -- * Evaluation
  , ($), ($!), ($!!), ($#), ($##), seq, ensureNotFree, ensureSpine
  , normalForm, groundNormalForm

  -- * Other Functions
  , (.), id, const, asTypeOf, curry, uncurry, flip, until
  , (&&), (||), not, otherwise, ifThenElse, maybe, either, fst, snd
  , failed, error

  -- * IO-Type and Operations
  , IO, getChar, getLine, putChar, putStr, putStrLn, print
  , FilePath, readFile, writeFile, appendFile
  , IOError (..), userError, ioError, catch

  -- * Constraint Programming
  , Success, success, solve, doSolve, (=:=), (=:<=), constrEq, (=:<<=)
  , (&), (&>)

  -- * Non-determinism
  , (?), anyOf, unknown

  -- * Internal Functions
  , apply, cond, eqString
  , DET, PEVAL
  ) where

infixr 9 .
infixl 9 !!
infixl 7 *, /, `div`, `mod`, `quot`, `rem`
infixl 6 +, -
infixr 5 ++
--++ The (:) operator is built-in syntax with the following fixity:
--++ infixr 5 :
infix  4 ==, /=, <, >, <=, >=
infix  4 ===, /==, =:=, =:<=, =:<<=
infix  4 `elem`, `notElem`
infixl 4 <$, <$>, <*>, <*, *>
infixl 3 <|>
infixr 3 &&
infixr 2 ||
infixl 1 >>, >>=
infixr 1 =<<
infixr 0 ?, $, $!, $!!, $#, $##, `seq`, &, &>

--- The externally defined type of characters.
external data Char

--- The externally defined type of integers.
external data Int

--- The externally defined type of float point numbers.
external data Float

--- The type of Boolean values.
data Bool = False | True

--- Ordering type. Useful as a result of comparison functions.
data Ordering = LT | EQ | GT

------------------------------------------------------------------------------
--++ data () = ()

--++ data (a, b) = (a, b)
--++ data (a, b, c) = (a, b, c)
--++ data (a, b, c, d) = (a, b, c, d)
--++ data (a, b, c, d, e) = (a, b, c, d, e)
--++ ...

--++ data [a] = [] | a : [a]

--++ data (->) a b

--- The class `Data` defines a strict equality operator `===`
--- and a non-deterministic operation `aValue` which yields
--- all values of the given type.
--- To ensure that the operator `===` always corresponds to the
--- syntactic equality of values and `aValue ` enumerates all values,
--- instances of `Data` are automatically derived and cannot be
--- defined in a valid Curry program.
--- For data types contain functional values, `Data` instances
--- are not derived.
--- Free variables have always a data context to ensure that possible
--- values for the type of the free variable can be enumerated.
---
--- Note that the class `Data` is different from the class `Eq`,
--- since the latter defines only an equivalence relation rather
--- than syntactic equality.
class Data a where
  (===)  :: a -> a -> Bool
  aValue :: a

--- The negation of strict equality.
(/==) :: Data a => a -> a -> Bool
x /== y = not (x ===y)

instance Data Char where
  (===) = (==)
  aValue = aValueChar

instance Data Int where
  (===) = (==)
  aValue = aValueInt

instance Data Float where
  (===) = (==)
  aValue = aValueFloat

instance Data a => Data [a] where
  []     === []     = True
  []     === (_:_)  = False
  (_:_)  === []     = False
  (x:xs) === (y:ys) = x === y && xs === ys

  aValue = [] ? (aValue:aValue)

instance Data () where
  () === () = True
  aValue = ()

instance (Data a, Data b) => Data (a, b) where
  (a1, b1) === (a2, b2) = a1 === a2 && b1 === b2
  aValue = (aValue, aValue)

instance (Data a, Data b, Data c) => Data (a, b, c) where
  (a1, b1, c1) === (a2, b2, c2) = a1 === a2 && b1 === b2 && c1 === c2
  aValue = (aValue, aValue, aValue)

instance (Data a, Data b, Data c, Data d) => Data (a, b, c, d) where
  (a1, b1, c1, d1) === (a2, b2, c2, d2) =
    a1 === a2 && b1 === b2 && c1 === c2 && d1 === d2
  aValue = (aValue, aValue, aValue, aValue)

instance (Data a, Data b, Data c, Data d, Data e) => Data (a, b, c, d, e) where
  (a1, b1, c1, d1, e1) === (a2, b2, c2, d2, e2) =
    a1 === a2 && b1 === b2 && c1 === c2 && d1 === d2 && e1 === e2
  aValue = (aValue, aValue, aValue, aValue, aValue)

instance (Data a, Data b, Data c, Data d, Data e, Data f) =>
         Data (a, b, c, d, e, f) where
  (a1, b1, c1, d1, e1, f1) === (a2, b2, c2, d2, e2, f2) =
    a1 === a2 && b1 === b2 && c1 === c2 && d1 === d2 && e1 === e2 && f1 === f2
  aValue = (aValue, aValue, aValue, aValue, aValue, aValue)

instance (Data a, Data b, Data c, Data d, Data e, Data f, Data g) =>
         Data (a, b, c, d, e, f, g) where
  (a1, b1, c1, d1, e1, f1, g1) === (a2, b2, c2, d2, e2, f2, g2) =
    a1 === a2 && b1 === b2 && c1 === c2 && d1 === d2 && e1 === e2 &&
    f1 === f2 && g1 === g2
  aValue = (aValue, aValue, aValue, aValue, aValue, aValue, aValue)

-- Value generator for positive natural numbers.
aValuePosNat :: Int
aValuePosNat = 1 ? (2 * aValuePosNat) ? (2 * aValuePosNat + 1)

-- Value generator for integers.
aValueInt :: Int
aValueInt = aValuePosNat ? 0 ?  (0 - aValuePosNat)

-- Value generator for floats. It is simply implemented by guessing the
-- two parts before and after the point. Could be replaced by other
-- enumeration methods.
aValueFloat :: Float
aValueFloat = aValuePosFloat ? 0 ? (0 - aValuePosFloat)

-- Value generator for positive floats. It is simply implemented by guessing
-- the two parts before and after the point. Could be replaced by other
-- enumeration methods.
aValuePosFloat :: Float
aValuePosFloat = fromInt aValuePosNat + nat2float 0.1 aValuePosNat
 where
  -- Transform a natural to float<1, e.g., nat2float 0.1 135 = 0.531
  nat2float :: Float -> Int -> Float
  nat2float m i =
    if i == 0 then 0
              else nat2float (m / 10) (i `div` 10) + m * fromInt (i `mod` 10)

-- Value generator for characters.
aValueChar :: Char
aValueChar = foldr1 (?) [minBound .. maxBound]

------------------------------------------------------------------------------

--- The class `Eq` defines an equality (`==`) and an inequality (`/=`) method.
--- Instances of this class should define an equivalence relationship
--- on values. For basic data types, the instances are defined as
--- syntactic equality of values.
class Eq a where
  (==), (/=) :: a -> a -> Bool

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

instance Eq Char where
  c == c' = c `eqChar` c'

instance Eq Int where
  i == i' = i `eqInt` i'

instance Eq Float where
  f == f' = f `eqFloat` f'

instance Eq () where
  () == () = True

instance (Eq a, Eq b) => Eq (a, b) where
  (a, b) == (a', b') = a == a' && b == b'

instance (Eq a, Eq b, Eq c) => Eq (a, b, c) where
  (a, b, c) == (a', b', c') = a == a' && b == b' && c == c'

instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d) where
  (a, b, c, d) == (a', b', c', d') = a == a' && b == b' && c == c' && d == d'

instance (Eq a, Eq b, Eq c, Eq d, Eq e) => Eq (a, b, c, d, e) where
  (a, b, c, d, e) == (a', b', c', d', e') =
    a == a' && b == b' && c == c' && d == d' && e == e'

instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f) => Eq (a, b, c, d, e, f) where
  (a, b, c, d, e, f) == (a', b', c', d', e', f') =
    a == a' && b == b' && c == c' && d == d' && e == e' && f == f'

instance Eq a => Eq [a] where
  []     == []     = True
  []     == (_:_)  = False
  (_:_)  == []     = False
  (x:xs) == (y:ys) = x == y && xs == ys

instance Eq Bool where
  False == False = True
  False == True  = False
  True  == False = False
  True  == True  = True

instance Eq Ordering where
  LT == LT = True
  LT == EQ = False
  LT == GT = False
  EQ == LT = False
  EQ == EQ = True
  EQ == GT = False
  GT == LT = False
  GT == EQ = False
  GT == GT = True

-- Equality on characters.
eqChar :: Char -> Char -> Bool
#ifdef __KICS2__
eqChar external
#elif  __KMCC__ > 0
eqChar external
#else
eqChar x y = (prim_eqChar $# y) $# x

prim_eqChar :: Char -> Char -> Bool
prim_eqChar external
#endif

-- Equality on integers.
eqInt :: Int -> Int -> Bool
#ifdef __KICS2__
eqInt external
#elif  __KMCC__ > 0
eqInt external
#else
eqInt x y = (prim_eqInt $# y) $# x

prim_eqInt :: Int -> Int -> Bool
prim_eqInt external
#endif

-- Equality on floating point numbers.
eqFloat :: Float -> Float -> Bool
#ifdef __KICS2__
eqFloat external
#elif  __KMCC__ > 0
eqFloat external
#else
eqFloat x y = (prim_eqFloat $# y) $# x

prim_eqFloat :: Float -> Float -> Bool
prim_eqFloat external
#endif

-- Equality on strings. We use a specialized implementation to aviod problems with kics2.
eqString :: String -> String -> Bool
eqString [] [] = True
eqString [] (_:_) = False
eqString (_:_) [] = False
eqString (x:xs) (y:ys) = eqChar x y && eqString xs ys

--- The class `Ord` defines operations to compare values of the given type
--- with respect to a total ordering.
--- A minimal instance definition for some type must define `<=` or `compare`.
class Eq a => Ord a where
  compare :: a -> a -> Ordering
  (<), (>), (<=), (>=) :: a -> a -> Bool
  min, max :: a -> a -> a

  compare x y | x == y = EQ
              | x <= y = LT
              | otherwise = GT
  x < y = x <= y && x /= y
  x > y = not (x <= y)
  x <= y = compare x y == EQ || compare x y == LT
  x >= y = y <= x
  min x y | x <= y = x
          | otherwise = y
  max x y | x >= y = x
          | otherwise = y

instance Ord Char where
  c1 <= c2 = c1 `ltEqChar` c2

instance Ord Int where
  i1 <= i2 = i1 `ltEqInt` i2

instance Ord Float where
  f1 <= f2 = f1 `ltEqFloat` f2

instance Ord () where
  () <= () = True

instance (Ord a, Ord b) => Ord (a, b) where
  (a, b) <= (a', b') = a < a' || (a == a' && b <= b')

instance (Ord a, Ord b, Ord c) => Ord (a, b, c) where
  (a, b, c) <= (a', b', c') = a < a'
    || (a == a' && b < b')
    || (a == a' && b == b' && c <= c')

instance (Ord a, Ord b, Ord c, Ord d) => Ord (a, b, c, d) where
  (a, b, c, d) <= (a', b', c', d') = a < a'
    || (a == a' && b < b')
    || (a == a' && b == b' && c < c')
    || (a == a' && b == b' && c == c' && d <= d')

instance (Ord a, Ord b, Ord c, Ord d, Ord e) => Ord (a, b, c, d, e) where
  (a, b, c, d, e) <= (a', b', c', d', e') = a < a'
    || (a == a' && b < b')
    || (a == a' && b == b' && c < c')
    || (a == a' && b == b' && c == c' && d < d')
    || (a == a' && b == b' && c == c' && d == d' && e <= e')

instance Ord a => Ord [a] where
  []     <= []     = True
  (_:_)  <= []     = False
  []     <= (_:_)  = True
  (x:xs) <= (y:ys) | x == y    = xs <= ys
                   | otherwise = x < y

instance Ord Bool where
  False <= False = True
  False <= True  = True
  True  <= False = False
  True  <= True  = True

instance Ord Ordering where
  LT <= LT = True
  LT <= EQ = True
  LT <= GT = True
  EQ <= LT = False
  EQ <= EQ = True
  EQ <= GT = True
  GT <= LT = False
  GT <= EQ = False
  GT <= GT = True

-- Compares two characters.
ltEqChar :: Char -> Char -> Bool
#ifdef __KICS2__
ltEqChar external
#elif  __KMCC__ > 0
ltEqChar external
#else
ltEqChar x y = (prim_ltEqChar $# y) $# x

prim_ltEqChar :: Char -> Char -> Bool
prim_ltEqChar external
#endif

-- Compares two integers.
ltEqInt :: Int -> Int -> Bool
#ifdef __KICS2__
ltEqInt external
#elif  __KMCC__ > 0
ltEqInt external
#else
ltEqInt x y = (prim_ltEqInt $# y) $# x

prim_ltEqInt :: Int -> Int -> Bool
prim_ltEqInt external
#endif

-- Compares two floating point numbers.
ltEqFloat :: Float -> Float -> Bool
#ifdef __KICS2__
ltEqFloat external
#elif  __KMCC__ > 0
ltEqFloat external
#else
ltEqFloat x y = (prim_ltEqFloat $# y) $# x

prim_ltEqFloat :: Float -> Float -> Bool
prim_ltEqFloat external
#endif

--- The type synonym `ShowS` represents strings as difference lists.
--- Composing functions of this type allows concatenation of lists
--- in constant time.
type ShowS = String -> String

--- The class `Show` contains methods to transform values into
--- a string representation.
class Show a where
  show :: a -> String
  showsPrec :: Int -> a -> ShowS
  showList :: [a] -> ShowS

  show x = shows x ""
  showsPrec _ x s = show x ++ s
  showList = showListDefault

instance Show Char where
  showsPrec _ c = showString (showCharLiteral c)
  showList cs | null cs   = showString "\"\""
              | otherwise = showString (showStringLiteral cs)

instance Show Int where
  showsPrec = showSigned (showString . showIntLiteral)

instance Show Float where
  showsPrec = showSigned (showString . showFloatLiteral)

instance Show () where
  showsPrec _ () = showString "()"

instance (Show a, Show b) => Show (a, b) where
  showsPrec _ (a, b) = showTuple [shows a, shows b]

instance (Show a, Show b, Show c) => Show (a, b, c) where
  showsPrec _ (a, b, c) = showTuple [shows a, shows b, shows c]

instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
  showsPrec _ (a, b, c, d) = showTuple [shows a, shows b, shows c, shows d]

instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where
  showsPrec _ (a, b, c, d, e) =
    showTuple [shows a, shows b, shows c, shows d, shows e]

instance (Show a, Show b, Show c, Show d, Show e, Show f) =>
         Show (a, b, c, d, e, f) where
  showsPrec _ (a, b, c, d, e, f) =
    showTuple [shows a, shows b, shows c, shows d, shows e, shows f]

instance Show a => Show [a] where
  showsPrec _ = showList

instance Show Bool where
  showsPrec _ False = showString "False"
  showsPrec _ True  = showString "True"

instance Show Ordering where
  showsPrec _ LT = showString "LT"
  showsPrec _ EQ = showString "EQ"
  showsPrec _ GT = showString "GT"

--- Converts a showable value to a show function that prepends this value.
shows :: Show a => a -> ShowS
shows = showsPrec 0

--- Converts a character to a show function that prepends the character.
showChar :: Char -> ShowS
showChar = (:)

--- Converts a string to a show function that prepends the string.
showString :: String -> ShowS
showString str s = foldr showChar s str

showListDefault :: Show a => [a] -> ShowS
showListDefault []     s = "[]" ++ s
showListDefault (x:xs) s = '[' : shows x (showl xs)
 where showl []     = ']' : s
       showl (y:ys) = ',' : shows y (showl ys)

--- If the first argument is `True`, Converts a show function to a
--- show function adding enclosing brackets, otherwise the show function
--- is returned unchanged.
showParen :: Bool -> ShowS -> ShowS
showParen b s = if b then showChar '(' . s . showChar ')' else s

showSigned :: Real a => (a -> ShowS) -> Int -> a -> ShowS
showSigned showPos p x
  | x < 0     = showParen (p > 6) (showChar '-' . showPos (-x))
  | otherwise = showPos x

--- Converts a list of show functions to a show function combining
--- the given show functions to a tuple representation.
showTuple :: [ShowS] -> ShowS
showTuple ss = showChar '('
             . foldr1 (\s r -> s . showChar ',' . r) ss
             . showChar ')'

-- Returns the string representation of a character.
showCharLiteral :: Char -> String
showCharLiteral x = prim_showCharLiteral $## x

prim_showCharLiteral :: Char -> String
prim_showCharLiteral external

-- Returns the string representation of a string.
showStringLiteral :: String -> String
showStringLiteral x = prim_showStringLiteral $## x

prim_showStringLiteral :: String -> String
prim_showStringLiteral external

-- Returns the string representation of an integer.
showIntLiteral :: Int -> String
showIntLiteral x = prim_showIntLiteral $## x

prim_showIntLiteral :: Int -> String
prim_showIntLiteral external

-- Returns the string representation of a floating point number.
showFloatLiteral :: Float -> String
showFloatLiteral x = prim_showFloatLiteral $## x

prim_showFloatLiteral :: Float -> String
prim_showFloatLiteral external


--- The type synonym `ReadS` represent a parser for values of type a.
--- Such a parser is a function that takes a String and
--- returns a list of possible parses as `(a,String)` pairs.
--- Thus, if the result is the empty list, there is no parse, i.e.,
--- the input string is not valid.
type ReadS a = String -> [(a, String)]

--- The class `Read` contains method to parse strings to return values
--- corresponding to the textual representation as produced by `show`.
class Read a where
  readsPrec :: Int -> ReadS a
  readList :: ReadS [a]

  readList = readListDefault

instance Read Char where
  readsPrec _ = readParen False
                  (\s -> [ (c, t) | (x, t) <- lex s, not (null x)
                                  , head x == '\''
                                  , (c, []) <- readCharLiteral x ])
  readList xs = readParen False
                  (\s -> [ (cs, t) | (x, t) <- lex s, not (null x)
                                   , head x == '"'
                                   , (cs, []) <- readStringLiteral x ]) xs
                ++ readListDefault xs

instance Read Int where
  readsPrec _ = readSigned (\s -> [ (i, t) | (x, t) <- lexDigits s
                                           , (i, []) <- readNatLiteral x ])

instance Read Float where
  readsPrec _ = readSigned
                  (\s -> [ (f, t) | (x, t) <- lex s, not (null x)
                                  , isDigit (head x), (f, []) <- readFloat x ])
   where
    readFloat x = if all isDigit x
                    then [(fromInt i, t) | (i, t) <- readNatLiteral x]
                    else readFloatLiteral x

instance Read () where
  readsPrec _ = readParen False (\r -> [ ((), t) | ("(", s) <- lex r
                                                 , (")", t) <- lex s ])

instance (Read a, Read b) => Read (a, b) where
  readsPrec _ = readParen False (\r -> [ ((a, b), w) | ("(", s) <- lex r
                                                     , (a, t) <- reads s
                                                     , (",", u) <- lex t
                                                     , (b, v) <- reads u
                                                     , (")", w) <- lex v ])

instance (Read a, Read b, Read c) => Read (a, b, c) where
  readsPrec _ = readParen False (\r -> [ ((a, b, c), y) | ("(", s) <- lex r
                                                        , (a, t) <- reads s
                                                        , (",", u) <- lex t
                                                        , (b, v) <- reads u
                                                        , (",", w) <- lex v
                                                        , (c, x) <- reads w
                                                        , (")", y) <- lex x ])

instance (Read a, Read b, Read c, Read d) => Read (a, b, c, d) where
  readsPrec _ = readParen False
                  (\q -> [ ((a, b, c, d), z) | ("(", r) <- lex q
                                             , (a, s) <- reads r
                                             , (",", t) <- lex s
                                             , (b, u) <- reads t
                                             , (",", v) <- lex u
                                             , (c, w) <- reads v
                                             , (",", x) <- lex w
                                             , (d, y) <- reads x
                                             , (")", z) <- lex y ])

instance (Read a, Read b, Read c, Read d, Read e) => Read (a, b, c, d, e) where
  readsPrec _ = readParen False
                  (\o -> [ ((a, b, c, d, e), z) | ("(", p) <- lex o
                                                , (a, q) <- reads p
                                                , (",", r) <- lex q
                                                , (b, s) <- reads r
                                                , (",", t) <- lex s
                                                , (c, u) <- reads t
                                                , (",", v) <- lex u
                                                , (d, w) <- reads v
                                                , (",", x) <- lex w
                                                , (e, y) <- reads x
                                                , (")", z) <- lex y ])

instance (Read a, Read b, Read c, Read d, Read e, Read f) =>
    Read (a, b, c, d, e, f) where
  readsPrec _ = readParen False
                  (\o -> [ ((a, b, c, d, e, f), z) | ("(", p) <- lex o
                                                   , (a, q) <- reads p
                                                   , (",", r) <- lex q
                                                   , (b, s) <- reads r
                                                   , (",", t) <- lex s
                                                   , (c, u) <- reads t
                                                   , (",", v) <- lex u
                                                   , (d, w) <- reads v
                                                   , (",", x) <- lex w
                                                   , (e, y) <- reads x
                                                   , (",", z1) <- lex y
                                                   , (f, z2) <- reads z1
                                                   , (")", z) <- lex z2 ])

instance Read a => Read [a] where
  readsPrec _ = readList

instance Read Bool where
  readsPrec _ r =
    readParen False (\s -> [(False, t) | ("False", t) <- lex s]) r ++
      readParen False (\s -> [(True, t) | ("True", t) <- lex s]) r

instance Read Ordering where
  readsPrec _ r =
    readParen False (\s -> [(LT, t) | ("LT", t) <- lex s]) r ++
      readParen False (\s -> [(EQ, t) | ("EQ", t) <- lex s]) r ++
      readParen False (\s -> [(GT, t) | ("GT", t) <- lex s]) r

--- A parser to read data from a string.
--- For instance, `reads "42" :: [(Int,String)]` returns `[(42,[])]`, and
--- `reads "hello" :: [(Int,String)]` returns `[]`.
reads :: Read a => ReadS a
reads = readsPrec 0

readListDefault :: Read a => ReadS [a]
readListDefault = readParen False (\r -> [pr | ("[",s) <- lex r, pr <- readl s])
 where readl s = [([], t) | ("]", t) <- lex s] ++
                   [(x : xs, u) | (x, t) <- reads s, (xs, u) <- readl' t]
       readl' s = [([], t) | ("]", t) <- lex s] ++
                   [ (x : xs, v) | (",", t)  <- lex s, (x, u) <- reads t
                                 , (xs,v) <- readl' u ]

--- `readParen True p` parses what `p` parses, but surrounded with parentheses.
--- `readParen False p` parses what `p` parses, but the string to be parsed
--- can be optionally with parentheses.
readParen :: Bool -> ReadS a -> ReadS a
readParen b g = if b then mandatory else optional
 where optional r = g r ++ mandatory r
       mandatory r =
         [(x, u) | ("(", s) <- lex r, (x, t) <- optional s, (")", u) <- lex t]

readSigned :: Real a => ReadS a -> ReadS a
readSigned p = readParen False read'
 where read' r = read'' r ++ [(-x, t) | ("-", s) <- lex r, (x, t) <- read'' s]
       read'' r = [(n, s) | (str, s) <- lex r, (n, "") <- p str]

--- Reads data of the given type from a string.
--- The operations fails if the data cannot be parsed.
--- For instance `read "42" :: Int` evaluates to `42`,
--- and `read "hello" :: Int` fails.
read :: Read a => String -> a
read s =  case [x | (x, t) <- reads s, ("", "") <- lex t] of
  [x] -> x

--- Reads a single lexeme from the given string.
--- Initial white space is discarded and the characters of the lexeme
--- are returned. If the input string contains only white space,
--- `lex` returns the empty string as lexeme.
--- If there is no legal lexeme at the beginning of the input string,
--- the operation fails, i.e., `[]` is returned.
lex :: ReadS String
lex xs = case xs of
  ""                  -> [("", "")]
  (c:cs) | isSpace c  -> lex $ dropWhile isSpace cs
  ('\'':s)            ->
    [('\'' : ch ++ "'", t) | (ch, '\'' : t)  <- lexCharLiteral s, ch /= "'"]
  ('"':s)             -> [('"' : str, t) | (str, t) <- lexString s]
  (c:cs) | isSingle c -> [([c], cs)]
         | isSymbol c -> [(c : sym, t) | (sym, t) <- [span isSymbol cs]]
         | isAlpha c  -> [(c : nam, t) | (nam, t) <- [span isIdChar cs]]
         | isDigit c  -> [ (c : ds ++ fe, t) | (ds, s) <- [span isDigit cs]
                                             , (fe, t) <- lexFracExp s ]
         | otherwise  -> []
 where
  isSingle c = c `elem` ",;()[]{}_`"
  isSymbol c = c `elem` "!@#$%&*+./<=>?\\^|:-~"
  isIdChar c = isAlphaNum c || c `elem` "_'"
  lexFracExp s = case s of
    ('.':c:cs) | isDigit c ->
      [('.' : ds ++ e, u) | (ds, t) <- lexDigits (c : cs), (e, u) <- lexExp t]
    _                      -> lexExp s
  lexExp s = case s of
    (e:cs) | e `elem` "eE" ->
      [ (e : c : ds, u) | (c:t) <- [cs], c `elem` "+-"
                        , (ds, u) <- lexDigits t ] ++
        [(e : ds, t) | (ds, t) <- lexDigits cs]
    _                      -> [("", s)]
  lexString s = case s of
    ('"':cs) -> [("\"", cs)]
    _        -> [ (ch ++ str, u) | (ch, t) <- lexStringItem s
                                  , (str, u) <- lexString t ]
  lexStringItem s = case s of
    ('\\':'&':cs)           -> [("\\&", cs)]
    ('\\':c:cs) | isSpace c -> [("\\&", t) | '\\':t <- [dropWhile isSpace cs]]
    _                       -> lexCharLiteral s

lexCharLiteral :: ReadS String
lexCharLiteral xs = case xs of
  ""        -> []
  ('\\':cs) -> map (prefix '\\') (lexEsc cs)
  (c:cs)    -> [([c], cs)]
 where
  lexEsc s = case s of
    (c:cs) | c `elem` "abfnrtv\\\"'"  -> [([c], cs)]
    ('^':c:cs) | c >= '@' && c <= '_' -> [(['^', c], cs)]
    ('b':cs)                          -> [prefix 'b' (span isBinDigit cs)]
    ('o':cs)                          -> [prefix 'o' (span isOctDigit cs)]
    ('x':cs)                          -> [prefix 'x' (span isHexDigit cs)]
    cs@(d:_) | isDigit d              -> [span isDigit cs]
    cs@(c:_) | isUpper c              -> [span isCharName cs]
    _                                 -> []
  isCharName c = isUpper c || isDigit c
  prefix c (t, cs) = (c : t, cs)

lexDigits :: ReadS String
lexDigits s = [(cs, t) | (cs@(_:_), t) <- [span isDigit s]]

readCharLiteral :: ReadS Char
readCharLiteral s = prim_readCharLiteral $## s

prim_readCharLiteral :: String -> [(Char, String)]
prim_readCharLiteral external

readStringLiteral :: ReadS String
readStringLiteral s = prim_readStringLiteral $## s

prim_readStringLiteral :: String -> [(String, String)]
prim_readStringLiteral external

readNatLiteral :: ReadS Int
readNatLiteral s = prim_readNatLiteral $## s

prim_readNatLiteral :: String -> [(Int, String)]
prim_readNatLiteral external

readFloatLiteral :: ReadS Float
readFloatLiteral s = prim_readFloatLiteral $## s

prim_readFloatLiteral :: String -> [(Float, String)]
prim_readFloatLiteral external

--- Instances of the class `Bounded` are types with minmal and maximal values.
class Bounded a where
  minBound, maxBound :: a

instance Bounded Char where
  minBound = chr 0
  maxBound = chr 0x10FFFF

instance Bounded () where
  minBound = ()
  maxBound = ()

instance (Bounded a, Bounded b) => Bounded (a, b) where
  minBound = (minBound, minBound)
  maxBound = (maxBound, maxBound)

instance (Bounded a, Bounded b, Bounded c) => Bounded (a, b, c) where
  minBound = (minBound, minBound, minBound)
  maxBound = (maxBound, maxBound, maxBound)

instance (Bounded a, Bounded b, Bounded c, Bounded d) => Bounded (a, b, c, d) where
  minBound = (minBound, minBound, minBound, minBound)
  maxBound = (maxBound, maxBound, maxBound, maxBound)

instance (Bounded a, Bounded b, Bounded c, Bounded d, Bounded e) =>
           Bounded (a, b, c, d, e) where
  minBound = (minBound, minBound, minBound, minBound, minBound)
  maxBound = (maxBound, maxBound, maxBound, maxBound, maxBound)

instance Bounded Bool where
  maxBound = False
  minBound = True

instance Bounded Ordering where
  maxBound = LT
  minBound = GT

--- The class `Enum` provides methods to enumerate values of the given
--- type in a sequential order.
--- If a type is an instance of `Enum`, one can use the standard
--- notation for arithmetic sequences to enumerate list of values.
class Enum a where
  succ :: a -> a
  pred :: a -> a
  toEnum :: Int -> a
  fromEnum :: a -> Int
  enumFrom :: a -> [a]
  enumFromThen :: a -> a -> [a]
  enumFromTo :: a -> a -> [a]
  enumFromThenTo :: a -> a -> a -> [a]

  succ = toEnum . (+ 1) . fromEnum
  pred = toEnum . (\x -> x - 1) . fromEnum
  enumFrom x = map toEnum [fromEnum x ..]
  enumFromThen x y = map toEnum [fromEnum x, fromEnum y ..]
  enumFromTo x y = map toEnum [fromEnum x .. fromEnum y]
  enumFromThenTo x y z = map toEnum [fromEnum x, fromEnum y .. fromEnum z]

instance Enum Char where
  succ c | c < maxBound = chr $ ord c + 1
  pred c | c > minBound = chr $ ord c - 1
  toEnum = chr
  fromEnum = ord
  enumFrom x = [x .. maxBound]
  enumFromThen x y | y >= x    = [x, y .. maxBound]
                   | otherwise = [x, y .. minBound]

instance Enum Int where
  succ x = x + 1
  pred x = x - 1
  toEnum n = n
  fromEnum n = n
  enumFrom x = x : enumFrom (x + 1)
  enumFromTo x y | x > y     = []
                 | otherwise = x : enumFromTo (x + 1) y
  enumFromThen x y = iterate ((y - x) +) x
  enumFromThenTo x y z = takeWhile p (enumFromThen x y)
   where p x' | y >= x    = x' <= z
              | otherwise = x' >= z

instance Enum () where
  succ _ = failed
  pred _ = failed
  toEnum 0 = ()
  fromEnum () = 0
  enumFrom () = [()]
  enumFromThen () () = let units = () : units in units
  enumFromTo () () = [()]
  enumFromThenTo () () () = let units = () : units in units

instance Enum Bool where
  succ False = True
  pred True  = False
  toEnum 0 = False
  toEnum 1 = True
  fromEnum False = 0
  fromEnum True  = 1
  enumFrom x = enumFromTo x True
  enumFromThen x y = enumFromThenTo x y (x <= y)

instance Enum Ordering where
  succ LT = EQ
  succ EQ = GT
  pred EQ = LT
  pred GT = EQ
  toEnum 0 = LT
  toEnum 1 = EQ
  toEnum 2 = GT
  fromEnum LT = 0
  fromEnum EQ = 1
  fromEnum GT = 2
  enumFrom x = enumFromTo x GT
  enumFromThen x y = enumFromThenTo x y (if x <= y then GT else LT)

--- The class of basic numeric values.
--- For type wich are instances of `Num`, one can write values
--- as integers which are converted by an implicit `fromInt` application.
class Num a where
  (+), (-), (*) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInt :: Int -> a

  x - y = x + negate y
  negate x = 0 - x

instance Num Int where
  x + y = x `plusInt` y
  x - y = x `minusInt` y
  x * y = x `timesInt` y
  negate x = 0 - x
  abs x | x >= 0    = x
        | otherwise = negate x
  signum x | x >  0    = 1
           | x == 0    = 0
           | otherwise = -1
  fromInt x = x

instance Num Float where
  x + y = x `plusFloat` y
  x - y = x `minusFloat` y
  x * y = x `timesFloat` y
  negate x = negateFloat x
  abs x | x >= 0    = x
        | otherwise = negate x
  signum x | x >  0    = 1
           | x == 0    = 0
           | otherwise = -1
  fromInt x = intToFloat x

-- Adds two integers.
plusInt :: Int -> Int -> Int
#ifdef __KICS2__
plusInt external
#elif  __KMCC__ > 0
plusInt external
#else
x `plusInt` y = (prim_plusInt $# y) $# x

prim_plusInt :: Int -> Int -> Int
prim_plusInt external
#endif

-- Subtracts two integers.
minusInt :: Int -> Int -> Int
#ifdef __KICS2__
minusInt external
#elif  __KMCC__ > 0
minusInt external
#else
x `minusInt` y = (prim_minusInt $# y) $# x

prim_minusInt :: Int -> Int -> Int
prim_minusInt external
#endif

-- Multiplies two integers.
timesInt :: Int -> Int -> Int
#ifdef __KICS2__
timesInt external
#elif  __KMCC__ > 0
timesInt external
#else
x `timesInt` y = (prim_timesInt $# y) $# x

prim_timesInt :: Int -> Int -> Int
prim_timesInt external
#endif

-- Adds two floating point numbers.
plusFloat :: Float -> Float -> Float
#ifdef __KMCC__
plusFloat external
#else
x `plusFloat` y = (prim_plusFloat $# y) $# x

prim_plusFloat :: Float -> Float -> Float
prim_plusFloat external
#endif

-- Subtracts two floating point numbers.
minusFloat :: Float -> Float -> Float
#ifdef __KMCC__
minusFloat external
#else
x `minusFloat` y = (prim_minusFloat $# y) $# x

prim_minusFloat :: Float -> Float -> Float
prim_minusFloat external
#endif

-- Multiplies two floating point numbers.
timesFloat :: Float -> Float -> Float
#ifdef __KMCC__
timesFloat external
#else
x `timesFloat` y = (prim_timesFloat $# y) $# x

prim_timesFloat :: Float -> Float -> Float
prim_timesFloat external
#endif

-- Negates a floating point number.
negateFloat :: Float -> Float
#ifdef __KICS2__
negateFloat external
#elif  __KMCC__ > 0
negateFloat external
#else
negateFloat x = prim_negateFloat $# x

prim_negateFloat :: Float -> Float
prim_negateFloat external
#endif

-- Converts from integers to floating point numbers.
intToFloat :: Int -> Float
#ifdef __KMCC__
intToFloat external
#else
intToFloat x = prim_intToFloat $# x

prim_intToFloat :: Int -> Float
prim_intToFloat external
#endif

--- The class `Fractional` defines numbers with a division operation.
class Num a => Fractional a where
  (/) :: a -> a -> a
  recip :: a -> a
  fromFloat :: Float -> a

  recip x = 1.0 / x
  x / y = x * recip y

instance Fractional Float where
  x / y = x `divFloat` y
  fromFloat x = x

-- Division on floating point numbers.
divFloat :: Float -> Float -> Float
#ifdef __KMCC__
divFloat external
#else
x `divFloat` y = (prim_divFloat $# y) $# x

prim_divFloat :: Float -> Float -> Float
prim_divFloat external
#endif

--- The class of real numbers which can be mapped to floats.
class (Num a, Ord a) => Real a where
  toFloat :: a -> Float

instance Real Int where
  toFloat x = fromInt x

instance Real Float where
  toFloat x = x

--- The class of `Integral` numbers supports integer division operators.
class (Real a, Enum a) => Integral a where
  div, mod :: a -> a -> a
  quot, rem :: a -> a -> a
  divMod :: a -> a -> (a, a)
  quotRem :: a -> a -> (a, a)
  toInt :: a -> Int

  n `div` d = q
   where (q, _) = divMod n d
  n `mod` d = r
   where (_, r) = divMod n d
  n `quot` d = q
   where (q, _) = quotRem n d
  n `rem` d = r
   where (_, r) = quotRem n d

instance Integral Int where
  divMod n d = (n `divInt` d, n `modInt` d)
  quotRem n d = (n `quotInt` d, n `remInt` d)
  toInt x = x

--- Returns whether an integer is even.
even :: Integral a => a -> Bool
even n = n `rem` 2 == 0

--- Returns whether an integer is odd.
odd :: Integral a => a -> Bool
odd = not . even

--- General coercion from integral types.
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInt . toInt

--- General coercion to fractional types.
realToFrac :: (Real a, Fractional b) => a -> b
realToFrac = fromFloat . toFloat

-- Integer division. The value is the integer quotient of its arguments
-- and always truncated towards negative infinity.
divInt :: Int -> Int -> Int
#ifdef __KICS2__
divInt external
#elif  __KMCC__ > 0
divInt external
#else
x `divInt` y = (prim_divInt $# y) $# x

prim_divInt :: Int -> Int -> Int
prim_divInt external
#endif

-- Integer remainder. The value is the remainder of the integer division
-- and it obeys the rule `mod x y = x - y * (div x y)`.
modInt :: Int -> Int -> Int
#ifdef __KICS2__
modInt external
#elif  __KMCC__ > 0
modInt external
#else
x `modInt` y = (prim_modInt $# y) $# x

prim_modInt :: Int -> Int -> Int
prim_modInt external
#endif

-- Integer division. The value is the integer quotient of its arguments
-- and always truncated towards zero.
quotInt :: Int -> Int -> Int
#ifdef __KICS2__
quotInt external
#elif  __KMCC__ > 0
quotInt external
#else
x `quotInt` y = (prim_quotInt $# y) $# x

prim_quotInt :: Int -> Int -> Int
prim_quotInt external
#endif

-- Integer remainder. The value is the remainder of the integer division
-- and it obeys the rule `rem x y = x - y * (quot x y)`.
remInt :: Int -> Int -> Int
#ifdef __KICS2__
remInt external
#elif  __KMCC__ > 0
remInt external
#else
x `remInt` y = (prim_remInt $# y) $# x

prim_remInt :: Int -> Int -> Int
prim_remInt external
#endif

--- Instances of the class `RealFrac` supports extracting components
--- of `Fractional` values.
class (Real a, Fractional a) => RealFrac a where
  properFraction :: Integral b => a -> (b, a)
  truncate :: Integral b => a -> b
  round :: Integral b => a -> b
  ceiling :: Integral b => a -> b
  floor :: Integral b => a -> b

  truncate x = m
   where (m, _) = properFraction x
  round x = let (n, r) = properFraction x
                m      = if r < 0 then n - 1 else n + 1
            in case compare (signum (abs r - 0.5)) 0 of
                 LT -> n
                 EQ -> if even n then n else m
                 GT -> m
  ceiling x = if r > 0 then n + 1 else n
   where (n, r) = properFraction x
  floor x = if r < 0 then n - 1 else n
   where (n, r) = properFraction x

instance RealFrac Float where
  properFraction x = (n, x - fromIntegral n)
   where n = truncate x
  truncate = fromInt . truncateFloat
  round = fromInt . roundFloat

-- Conversion function from floating point numbers to integers.
-- The result is the closest integer between the argument and 0.
truncateFloat :: Float -> Int
#ifdef __KMCC__
truncateFloat external
#else
truncateFloat x = prim_truncateFloat $# x

prim_truncateFloat :: Float -> Int
prim_truncateFloat external
#endif

-- Conversion function from floating point numbers to integers.
-- The result is the nearest integer to the argument.
-- If the argument is equidistant between two integers,
-- it is rounded to the closest even integer value.
roundFloat :: Float -> Int
#ifdef __KMCC__
roundFloat external
#else
roundFloat x = prim_roundFloat $# x

prim_roundFloat :: Float -> Int
prim_roundFloat external
#endif

--- The class `Floating` defines `Fractional`s with
--- trigonometric and hyperbolic and related functions.
class Fractional a => Floating a where
  pi :: a
  exp, log, sqrt :: a -> a
  (**), logBase :: a -> a -> a
  sin, cos, tan :: a -> a
  asin, acos, atan :: a -> a
  sinh, cosh, tanh :: a -> a
  asinh, acosh, atanh :: a -> a

  sqrt x = x ** 0.5
  x ** y = exp (log x * y)
  logBase x y = log y / log x
  tan x = sin x / cos x
  tanh x = sinh x / cosh x

instance Floating Float where
  pi = 3.141592653589793238
  exp = expFloat
  log = logFloat
  sqrt = sqrtFloat
  sin = sinFloat
  cos = cosFloat
  tan = tanFloat
  asin = asinFloat
  acos = acosFloat
  atan = atanFloat
  sinh = sinhFloat
  cosh = coshFloat
  tanh = tanhFloat
  asinh = asinhFloat
  acosh = acoshFloat
  atanh = atanhFloat

-- Natural logarithm.
logFloat :: Float -> Float
#ifdef __KMCC__
logFloat external
#else
logFloat x = prim_logFloat $# x

prim_logFloat :: Float -> Float
prim_logFloat external
#endif

-- Natural exponent.
expFloat :: Float -> Float
#ifdef __KMCC__
expFloat external
#else
expFloat x = prim_expFloat $# x

prim_expFloat :: Float -> Float
prim_expFloat external
#endif

-- Square root.
sqrtFloat :: Float -> Float
#ifdef __KMCC__
sqrtFloat external
#else
sqrtFloat x = prim_sqrtFloat $# x

prim_sqrtFloat :: Float -> Float
prim_sqrtFloat external
#endif

-- Sine.
sinFloat :: Float -> Float
#ifdef __KMCC__
sinFloat external
#else
sinFloat x = prim_sinFloat $# x

prim_sinFloat :: Float -> Float
prim_sinFloat external
#endif

-- Cosine.
cosFloat :: Float -> Float
#ifdef __KMCC__
cosFloat external
#else
cosFloat x = prim_cosFloat $# x

prim_cosFloat :: Float -> Float
prim_cosFloat external
#endif

-- Tangent.
tanFloat :: Float -> Float
#ifdef __KMCC__
tanFloat external
#else
tanFloat x = prim_tanFloat $# x

prim_tanFloat :: Float -> Float
prim_tanFloat external
#endif

-- Arcus sine.
asinFloat :: Float -> Float
#ifdef __KMCC__
asinFloat external
#else
asinFloat x = prim_asinFloat $# x

prim_asinFloat :: Float -> Float
prim_asinFloat external
#endif

-- Arcus cosine.
acosFloat :: Float -> Float
#ifdef __KMCC__
acosFloat external
#else
acosFloat x = prim_acosFloat $# x

prim_acosFloat :: Float -> Float
prim_acosFloat external
#endif

-- Arcus tangent.
atanFloat :: Float -> Float
#ifdef __KMCC__
atanFloat external
#else
atanFloat x = prim_atanFloat $# x

prim_atanFloat :: Float -> Float
prim_atanFloat external
#endif

-- Hyperbolic sine.
sinhFloat :: Float -> Float
#ifdef __KMCC__
sinhFloat external
#else
sinhFloat x = prim_sinhFloat $# x

prim_sinhFloat :: Float -> Float
prim_sinhFloat external
#endif

-- Hyperbolic cosine.
coshFloat :: Float -> Float
#ifdef __KMCC__
coshFloat external
#else
coshFloat x = prim_coshFloat $# x

prim_coshFloat :: Float -> Float
prim_coshFloat external
#endif

-- Hyperbolic tangent.
tanhFloat :: Float -> Float
#ifdef __KMCC__
tanhFloat external
#else
tanhFloat x = prim_tanhFloat $# x

prim_tanhFloat :: Float -> Float
prim_tanhFloat external
#endif

-- Hyperbolic arcus sine.
asinhFloat :: Float -> Float
#ifdef __KMCC__
asinhFloat external
#else
asinhFloat x = prim_asinhFloat $# x

prim_asinhFloat :: Float -> Float
prim_asinhFloat external
#endif

-- Hyperbolic arcus cosine.
acoshFloat :: Float -> Float
#ifdef __KMCC__
acoshFloat external
#else
acoshFloat x = prim_acoshFloat $# x

prim_acoshFloat :: Float -> Float
prim_acoshFloat external
#endif

-- Hyperbolic arcus tangent.
atanhFloat :: Float -> Float
#ifdef __KMCC__
atanhFloat external
#else
atanhFloat x = prim_atanhFloat $# x

prim_atanhFloat :: Float -> Float
prim_atanhFloat external
#endif

--- Raises a number to a non-negative integer power.
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0    = error "Negative exponent"
        | y0 == 0   = 1
        | otherwise = f x0 y0
    where -- f : x0 ^ y0 = x ^ y
          f x y | even y    = f (x * x) (y `quot` 2)
                | y == 1    = x
                | otherwise = g (x * x) (y `quot` 2) x
          -- g : x0 ^ y0 = (x ^ y) * z
          g x y z | even y = g (x * x) (y `quot` 2) z
                  | y == 1 = x * z
                  | otherwise = g (x * x) (y `quot` 2) (x * z)

--- The class `Monoid` defines types with an associative
--- binary operation `mappend` having an identity `mempty`.
class Monoid a where
  mempty  :: a
  mappend :: a -> a -> a
  mconcat :: [a] -> a

  mconcat = foldr mappend mempty

instance Monoid () where
  mempty = ()
  _ `mappend` _ = ()
  mconcat _ = ()

instance (Monoid a, Monoid b) => Monoid (a, b) where
  mempty = (mempty, mempty)
  (a1, b1) `mappend` (a2,b2) = (a1 `mappend` a2, b1 `mappend` b2)

instance (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c) where
  mempty = (mempty, mempty, mempty)
  (a1, b1, c1) `mappend` (a2, b2, c2) =
    (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2)

instance (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a, b, c, d) where
  mempty = (mempty, mempty, mempty, mempty)
  (a1, b1, c1, d1) `mappend` (a2, b2, c2, d2) =
    (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2, d1 `mappend` d2)

instance (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) =>
           Monoid (a, b, c, d, e) where
  mempty = (mempty, mempty, mempty, mempty, mempty)
  (a1, b1, c1, d1, e1) `mappend` (a2, b2, c2, d2, e2) =
    (a1 `mappend` a2, b1 `mappend` b2, c1 `mappend` c2, d1 `mappend` d2,
      e1 `mappend` e2)

instance Monoid [a] where
  mempty  = []
  mappend = (++)
  mconcat xss = [x | xs <- xss, x <- xs]

instance Monoid b => Monoid (a -> b) where
  mempty _ = mempty
  mappend f g x = f x `mappend` g x

instance Monoid Ordering where
  mempty = EQ
  LT `mappend` _ = LT
  EQ `mappend` y = y
  GT `mappend` _ = GT

--- The class `Functor` defines a general mapping of values contained
--- in structures.
--- A type constructor `f` is a Functor if it provides a function `fmap`
--- which applies a function of type `(a -> b)` to all values contained
--- in a structure of type `f a` yielding a structure of type `f b`.
class Functor f where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a

  (<$) = fmap . const

instance Functor [] where
  fmap = map

instance Functor ((->) r) where
  fmap = (.)

--- Apply a function of type `(a -> b)`, given as the left argument,
--- to a value of type `f a`, where `f` is a functor,
--- to get a value of type `f b`.
--- Basically, this is an infix operator version of `fmap`.
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<$>) = fmap

--- The class `Applicative` defines a functor structure
--- with application operators to apply functions and argument
--- contained in structure and combining their results back into a structure.
class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
  (*>) :: f a -> f b -> f b
  (<*) :: f a -> f b -> f a
  liftA2 :: (a -> b -> c) -> f a -> f b -> f c

  (<*>) = liftA2 id
  a1 *> a2 = (id <$ a1) <*> a2
  (<*) = liftA2 const
  liftA2 f x = (<*>) (fmap f x)

instance Applicative [] where
  pure x    = [x]
  fs <*> xs = [f x | f <- fs, x <- xs]
  xs *> ys  = [y | _ <- xs, y <- ys]
  liftA2 f xs ys = [f x y | x <- xs, y <- ys]

instance Applicative ((->) a) where
  pure = const
  (<*>) f g x = f x (g x)
  liftA2 q f g x = q (f x) (g x)


-- | A monoid on applicative functors.
--
-- If defined, 'some' and 'many' should be the least solutions
-- of the equations:
--
-- * @'some' v = (:) '<$>' v '<*>' 'many' v@
--
-- * @'many' v = 'some' v '<|>' 'pure' []@
class Applicative f => Alternative f where
    -- | The identity of '<|>'
    empty :: f a
    -- | An associative binary operation
    (<|>) :: f a -> f a -> f a

    -- | One or more.
    some :: f a -> f [a]
    some v = some_ v
      where
        many_ x = some_ x <|> pure []
        some_ x = (:) <$> x <*> many_ x

    -- | Zero or more.
    many :: f a -> f [a]
    many v = many_ v
      where
        many_ x = some_ x <|> pure []
        some_ x = (:) <$> x <*> many_ x

instance Alternative [] where
    empty = []
    (<|>) = (++)

--- The class `Monad` defines operators for the sequential composition
--- of computations.
--- For instances of `Monad`, the standard `do` notation can be used.
class Applicative m => Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a

  return = pure
  m >> k = m >>= \_ -> k

instance Monad [] where
  xs >>= f = [y | x <- xs, y <- f x]
  (>>) = (*>)

instance Monad ((->) r) where
  f >>= k = \ r -> k (f r) r

--- The class `MonadFail` adds a `fail` operation to a monadic structure.
class Monad m => MonadFail m where
  fail :: String -> m a

instance MonadFail [] where
  fail _ = []

--- Same as '>>=', but with the arguments interchanged.
(=<<) :: Monad m => (a -> m b) -> m a -> m b
f =<< x = x >>= f

--- Promotes function application to a monad.
--- For instance,
---
---     > pure not `ap` Just True
---     Just False
---
--- This is useful to promote application of functions with larger arities
--- to a monad, as 'liftM2' for arity `2`. For instance,
---
---     > pure (\x y z -> x + y * z) `ap` Just 7 `ap` Just 5 `ap` Just 7
---     Just 42
ap :: Monad m => m (a -> b) -> m a -> m b
ap m1 m2 = do
  x1 <- m1
  x2 <- m2
  return (x1 x2)

--- Promotes a binary function to a monad.
--- The function arguments are scanned from left to right.
--- For instance, `liftM2 (+) [1,2] [3,4]` evaluates to `[4,5,5,6]`, and
--- `liftM2 (,) [1,2] [3,4]` evaluates to `[(1,3),(1,4),(2,3),(2,4)]`.
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do
  x1 <- m1
  x2 <- m2
  return (f x1 x2)

--- Executes a sequence of monadic actions and collects all results in a list.
sequence :: Monad m => [m a] -> m [a]
sequence []     = return []
sequence (c:cs) = do x <- c
                     xs <- sequence cs
                     return (x : xs)

--- Executes a sequence of monadic actions and ignores the results.
sequence_ :: Monad m => [m _] -> m ()
sequence_ = foldr (>>) (return ())

--- Maps a monadic action function on a list of elements.
--- The results of all monadic actions are collected in a list.
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f = sequence . map f

--- Maps a monadic action function on a list of elements.
--- The results of all monadic actions are ignored.
mapM_ :: Monad m => (a -> m _) -> [a] -> m ()
mapM_ f = sequence_ . map f

--- Returns true if the argument is an uppercase letter.
isUpper :: Char -> Bool
isUpper c = c >= 'A' && c <= 'Z'

--- Returns true if the argument is an lowercase letter.
isLower :: Char -> Bool
isLower c = c >= 'a' && c <= 'z'

--- Returns true if the argument is a letter.
isAlpha :: Char -> Bool
isAlpha c = isUpper c || isLower c

--- Returns true if the argument is a decimal digit.
isDigit :: Char -> Bool
isDigit c = c >= '0' && c <= '9'

--- Returns true if the argument is a letter or digit.
isAlphaNum :: Char -> Bool
isAlphaNum c = isAlpha c || isDigit c

--- Returns true if the argument is a binary digit.
isBinDigit :: Char -> Bool
isBinDigit c = c == '0' || c == '1'

--- Returns true if the argument is an octal digit.
isOctDigit :: Char -> Bool
isOctDigit c = c >= '0' && c <= '7'

--- Returns true if the argument is a hexadecimal digit.
isHexDigit :: Char -> Bool
isHexDigit c = isDigit c || c >= 'A' && c <= 'F'
                         || c >= 'a' && c <= 'f'

--- Returns true if the argument is a white space.
isSpace :: Char -> Bool
isSpace c = c == ' '    || c == '\t' || c == '\n' ||
            c == '\r'   || c == '\f' || c == '\v' ||
            c == '\xa0' || ord c `elem` [5760, 6158, 8192, 8239, 8287, 12288]

--- Converts a character into its ASCII value.
ord :: Char -> Int
ord c = prim_ord $# c

prim_ord :: Char -> Int
prim_ord external

--- Converts a Unicode value into a character.
--- The conversion is total, i.e., for out-of-bound values, the smallest
--- or largest character is generated.
chr :: Int -> Char
chr n | n < 0       = prim_chr 0
      | n > 1114111 = prim_chr 1114111
      | otherwise   = prim_chr $# n

prim_chr :: Int -> Char
prim_chr external

--- The type `String` is a type synonym for list of characters so that
--- all list operations can be used on strings.
type String = [Char]

--- Breaks a string into a list of lines where a line is terminated at a
--- newline character. The resulting lines do not contain newline characters.
lines :: String -> [String]
lines []       = []
lines as@(_:_) = let (l, bs) = splitLine as in l : lines bs
 where splitLine []     = ([], [])
       splitLine (c:cs) = if c == '\n' then ([], cs)
                                       else let (ds, es) = splitLine cs
                                            in (c : ds, es)

--- Concatenates a list of strings with terminating newlines.
unlines :: [String] -> String
unlines = concatMap (++ "\n")

--- Breaks a string into a list of words where the words are delimited by
--- white spaces.
words :: String -> [String]
words s = let s1 = dropWhile isSpace s
          in if s1 == "" then []
                         else let (w, s2) = break isSpace s1
                              in w : words s2

--- Concatenates a list of strings with a blank between two strings.
unwords :: [String] -> String
unwords ws = if null ws then []
                        else foldr1 (\w s -> w ++ ' ' : s) ws


--- Right-associative application.
($) :: (a -> b) -> a -> b
f $ x = f x

--- Right-associative application with strict evaluation of its argument
--- to head normal form.
($!) :: (a -> b) -> a -> b
($!) external

--- Right-associative application with strict evaluation of its argument
--- to normal form.
($!!) :: (a -> b) -> a -> b
($!!) external

--- Right-associative application with strict evaluation of its argument
--- to a non-variable term.
($#) :: (a -> b) -> a -> b
f $# x = f $! (ensureNotFree x)

--- Right-associative application with strict evaluation of its argument
--- to ground normal form.
($##) :: (a -> b) -> a -> b
($##) external

--- Evaluates the first argument to head normal form (which could also
--- be a free variable) and returns the second argument.
seq :: _ -> a -> a
x `seq` y = const y $! x

--- Evaluates the argument to head normal form and returns it.
--- Suspends until the result is bound to a non-variable term.
ensureNotFree :: a -> a
ensureNotFree external

--- Evaluates the argument to spine form and returns it.
--- Suspends until the result is bound to a non-variable spine.
ensureSpine :: [a] -> [a]
ensureSpine l = ensureList (ensureNotFree l)
 where ensureList []     = []
       ensureList (x:xs) = x : ensureSpine xs

--- Evaluates the argument to normal form and returns it.
normalForm :: a -> a
normalForm x = id $!! x

--- Evaluates the argument to ground normal form and returns it.
--- Suspends as long as the normal form of the argument is not ground.
groundNormalForm :: a -> a
groundNormalForm x = id $## x


--- Function composition.
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \x -> f (g x)

--- Identity function.
id :: a -> a
id x = x

--- Constant function.
const :: a -> _ -> a
const x _ = x

--- `asTypeOf` is a type-restricted version of `const`.
--- It is usually used as an infix operator, and its typing forces its first
--- argument (which is usually overloaded) to have the same type as the second.
asTypeOf :: a -> a -> a
asTypeOf = const

--- Converts an uncurried function to a curried function.
curry :: ((a, b) -> c) -> a -> b -> c
curry f a b =  f (a, b)

--- Converts an curried function to a function on pairs.
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f (a, b) = f a b

--- `flip f` is identical to `f`, but with the order of arguments reversed.
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x

--- Repeats application of a function until a predicate holds.
until :: (a -> Bool) -> (a -> a) -> a -> a
until p f x = if p x then x else until p f (f x)


--- Sequential conjunction on Booleans.
(&&) :: Bool -> Bool -> Bool
True  && x = x
False && _ = False

--- Sequential disjunction on Booleans.
(||) :: Bool -> Bool -> Bool
True  || _ = True
False || x = x

--- Negation on Booleans.
not :: Bool -> Bool
not True  = False
not False = True

--- Useful name for the last condition in a sequence of conditional equations.
otherwise :: Bool
otherwise = True

--- The standard conditional. It suspends if the condition is a free variable.
ifThenElse :: Bool -> a -> a -> a
ifThenElse b t f = case b of True  -> t
                             False -> f

--- Selects the first component of a pair.
fst :: (a, _) -> a
fst (x, _) = x

--- Selects the second component of a pair.
snd :: (_, b) -> b
snd (_, y) = y


--- Computes the first element of a list.
head :: [a] -> a
head (x:_) = x

--- Computes the remaining elements of a list.
tail :: [a] -> [a]
tail (_:xs) = xs

--- Is a list empty?
null :: [_] -> Bool
null []    = True
null (_:_) = False

--- Concatenates two lists.
--- Since it is flexible, it could be also used to split a list
--- into two sublists etc.
(++) :: [a] -> [a] -> [a]
[]     ++ ys = ys
(x:xs) ++ ys = x : xs ++ ys

--- Computes the length of a list.
length :: [_] -> Int
length [] = 0
length (_:xs) = 1 + length xs

--- List index (subscript) operator, head has index 0.
(!!) :: [a] -> Int -> a
(x:xs) !! n | n == 0 = x
            | n > 0  = xs !! (n - 1)

--- Maps a function on all elements of a list.
map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs

--- Accumulates all list elements by applying a binary operator from
--- left to right.
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl _ z []     = z
foldl f z (x:xs) = foldl f (f z x) xs

--- Accumulates a non-empty list from left to right.
foldl1 :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs) = foldl f x xs

--- Accumulates all list elements by applying a binary operator from
--- right to left.
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z []     = z
foldr f z (x:xs) = f x (foldr f z xs)

--- Accumulates a non-empty list from right to left:
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 _ [x]          = x
foldr1 f (x:xs@(_:_)) = f x (foldr1 f xs)

--- Filters all elements satisfying a given predicate in a list.
filter :: (a -> Bool) -> [a] -> [a]
filter _ []     = []
filter p (x:xs) = if p x then x : filter p xs
                         else filter p xs

--- Joins two lists into one list of pairs. If one input list is shorter than
--- the other, the additional elements of the longer list are discarded.
zip :: [a] -> [b] -> [(a, b)]
zip []     _      = []
zip (_:_)  []     = []
zip (x:xs) (y:ys) = (x, y) : zip xs ys

--- Joins three lists into one list of triples. If one input list is shorter
--- than the other, the additional elements of the longer lists are discarded.
zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
zip3 []     _      _      = []
zip3 (_:_)  []     _      = []
zip3 (_:_)  (_:_)  []     = []
zip3 (x:xs) (y:ys) (z:zs) = (x, y, z) : zip3 xs ys zs

--- Joins two lists into one list by applying a combination function to
--- corresponding pairs of elements. Thus `zip = zipWith (,)`
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith _ []     _      = []
zipWith _ (_:_)  []     = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys

--- Joins three lists into one list by applying a combination function to
--- corresponding triples of elements. Thus `zip3 = zipWith3 (,,)`
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 _ []     _      _      = []
zipWith3 _ (_:_)  []     _      = []
zipWith3 _ (_:_)  (_:_)  []     = []
zipWith3 f (x:xs) (y:ys) (z:zs) = f x y z : zipWith3 f xs ys zs

--- Transforms a list of pairs into a pair of lists.
unzip :: [(a, b)] -> ([a], [b])
unzip []          = ([], [])
unzip ((x, y):ps) = (x : xs, y : ys)
 where (xs, ys) = unzip ps

--- Transforms a list of triples into a triple of lists.
unzip3 :: [(a, b, c)] -> ([a], [b], [c])
unzip3 []             = ([], [], [])
unzip3 ((x, y, z):ts) = (x : xs, y : ys, z : zs)
 where (xs, ys, zs) = unzip3 ts

--- Concatenates a list of lists into one list.
concat :: [[a]] -> [a]
concat = foldr (++) []

--- Maps a function from elements to lists and merges the result into one list.
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f = concat . map f

--- Infinite list of repeated applications of a function f to an element x.
--- Thus, `iterate f x = [x, f x, f (f x), ...]`.
iterate :: (a -> a) -> a -> [a]
iterate f x = x : iterate f (f x)

--- Infinite list where all elements have the same value.
--- Thus, `repeat x = [x, x, x, ...]`.
repeat :: a -> [a]
repeat x = x : repeat x

--- List of length n where all elements have the same value.
replicate :: Int -> a -> [a]
replicate n x = take n (repeat x)

--- Returns prefix of length n.
take :: Int -> [a] -> [a]
take n l = if n <= 0 then [] else takep n l
 where takep _ []     = []
       takep m (x:xs) = x : take (m - 1) xs

--- Returns suffix without first n elements.
drop :: Int -> [a] -> [a]
drop n xs = if n <= 0 then xs
                      else case xs of []     -> []
                                      (_:ys) -> drop (n - 1) ys

--- `splitAt n xs` is equivalent to `(take n xs, drop n xs)`
splitAt :: Int -> [a] -> ([a], [a])
splitAt n l = if n <= 0 then ([], l) else splitAtp n l
  where splitAtp _ []     = ([], [])
        splitAtp m (x:xs) = let (ys, zs) = splitAt (m - 1) xs in (x : ys, zs)

--- Returns longest prefix with elements satisfying a predicate.
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile _ []     = []
takeWhile p (x:xs) = if p x then x : takeWhile p xs else []

--- Returns suffix without takeWhile prefix.
dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile _ []     = []
dropWhile p (x:xs) = if p x then dropWhile p xs else x : xs

--- `span p xs` is equivalent to `(takeWhile p xs, dropWhile p xs)`
span :: (a -> Bool) -> [a] -> ([a], [a])
span _ []     = ([], [])
span p (x:xs) | p x       = let (ys, zs) = span p xs in (x : ys, zs)
              | otherwise = ([], x : xs)

--- `break p xs` is equivalent to
--- `(takeWhile (not . p) xs, dropWhile (not . p) xs)`.
--- Thus, it breaks a list at the first occurrence of an element satisfying p.
break :: (a -> Bool) -> [a] -> ([a], [a])
break p = span (not . p)

--- Reverses the order of all elements in a list.
reverse :: [a] -> [a]
reverse = foldl (flip (:)) []

--- Computes the conjunction of a Boolean list.
and :: [Bool] -> Bool
and = foldr (&&) True

--- Computes the disjunction of a Boolean list.
or :: [Bool] -> Bool
or = foldr (||) False

--- Is there an element in a list satisfying a given predicate?
any :: (a -> Bool) -> [a] -> Bool
any p = or . map p

--- Is a given predicate satisfied by all elements in a list?
all :: (a -> Bool) -> [a] -> Bool
all p = and . map p

--- Element of a list?
elem :: Eq a => a -> [a] -> Bool
elem x = any (x ==)

--- Not element of a list?
notElem :: Eq a => a -> [a] -> Bool
notElem x = all (x /=)

--- Looks up a key in an association list.
lookup :: Eq a => a -> [(a, b)] -> Maybe b
lookup _ []          = Nothing
lookup k ((x,y):xys) | k == x    = Just y
                     | otherwise = lookup k xys

--- The `Maybe` type can be used for values which could also be absent.
data Maybe a = Nothing | Just a
 deriving (Eq, Ord, Show, Read)

instance Monoid a => Monoid (Maybe a) where
  mempty = Nothing
  Nothing `mappend` m       = m
  Just m1 `mappend` Nothing = Just m1
  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)

instance Functor Maybe where
  fmap _ Nothing  = Nothing
  fmap f (Just x) = Just (f x)

instance Applicative Maybe where
  pure = Just
  Just f  <*> m = fmap f m
  Nothing <*> _ = Nothing
  Just _  *> m = m
  Nothing *> _ = Nothing
  liftA2 f (Just x) (Just y) = Just (f x y)
  liftA2 _ (Just _) Nothing  = Nothing
  liftA2 _ Nothing  _        = Nothing

instance Alternative Maybe where
    empty = Nothing
    Nothing <|> r = r
    Just l  <|> _ = Just l

instance Monad Maybe where
  Nothing >>= _ = Nothing
  Just x  >>= k = k x
  (>>) = (*>)

instance MonadFail Maybe where
  fail _ = Nothing

--- The `maybe` function takes a default value, a function, and a `Maybe` value.
--- If the `Maybe` value is `Nothing`, the default value is returned.
--- Otherwise, the function is applied to the value inside the `Just`
--- and the result is returned.
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing  = n
maybe _ f (Just x) = f x

--- The `Either` type can be used to combine values of two different types.
data Either a b = Left a
                | Right b
  deriving (Eq, Ord, Show, Read)

instance Functor (Either a) where
  fmap _ (Left e)  = Left e
  fmap f (Right x) = Right (f x)

instance Applicative (Either a) where
  pure = Right
  (<*>) = ap

instance Monad (Either a) where
  return          = Right
  (Left e)  >>= _ = Left e
  (Right x) >>= f = f x

--- Apply a case analysis to a value of the Either type.
--- If the value is `Left x`, the first function is applied to `x`.
--- If the value is `Right y`, the second function is applied to `y`.
either :: (a -> c) -> (b -> c) -> Either a b -> c
either left _     (Left  a) = left a
either _    right (Right b) = right b

--- The externally defined type of IO actions.
external data IO _

instance Monoid a => Monoid (IO a) where
  mempty = pure mempty
  mappend = liftA2 mappend

instance  Functor IO where
  fmap f x = x >>= (pure . f)

instance Applicative IO where
  pure = returnIO
  m *> k = m >>= \_ -> k
  (<*>) = ap
  liftA2 = liftM2

instance Alternative IO where
    empty = fail "mzero"

    m <|> n = m `catch` const n

instance Monad IO where
  (>>=) = bindIO
  (>>) = (*>)

instance MonadFail IO where
  fail s = ioError (userError s)

bindIO :: IO a -> (a -> IO b) -> IO b
bindIO external

returnIO :: a -> IO a
returnIO external

--- An action that reads a character from standard output and returns it.
getChar :: IO Char
getChar external

--- An action that reads a line from standard input and returns it.
getLine :: IO String
getLine = do c <- getChar
             case c of
               '\n' -> return []
               _ -> do cs <- getLine
                       return (c : cs)

--- An action that puts its character argument on standard output.
putChar :: Char -> IO ()
putChar c = prim_putChar $# c

prim_putChar :: Char -> IO ()
prim_putChar external

--- Action to print a string on standard output.
putStr :: String -> IO ()
putStr []     = return ()
putStr (c:cs) = putChar c >> putStr cs

--- Action to print a string with a newline on standard output.
putStrLn :: String -> IO ()
putStrLn cs = putStr cs >> putChar '\n'

--- Converts a term into a string and prints it.
print :: Show a => a -> IO ()
print = putStrLn . show

--- The `FilePath` is j type synonym for strings.
--- It is useful to mark in type signatures if a file path is required.
type FilePath = String

--- An action that (lazily) reads a file and returns its contents.
readFile :: FilePath -> IO String
readFile f = prim_readFile $## f

prim_readFile :: FilePath -> IO String
prim_readFile external

#ifdef __PAKCS__
-- Needed for internal implementation of readFile.
prim_readFileContents :: FilePath -> String
prim_readFileContents external
#endif

--- An action that writes a file.
writeFile :: FilePath -> String -> IO ()
writeFile f s = (prim_writeFile $## f) s

prim_writeFile :: FilePath -> String -> IO ()
prim_writeFile external

--- An action that appends a string to a file.
--- It behaves like `writeFile` if the file does not exist.
appendFile :: FilePath -> String -> IO ()
appendFile f s = (prim_appendFile $## f) s

prim_appendFile :: FilePath -> String -> IO ()
prim_appendFile external

--- The (abstract) type of error values.
--- Currently, it distinguishes between general I/O errors,
--- user-generated errors (see 'userError'), failures and non-determinism
--- errors during I/O computations. These errors can be caught by 'catch'.
--- Each error contains a string shortly explaining the error.
--- This type might be extended in the future to distinguish
--- further error situations.
data IOError
  = IOError String     -- normal IO error
  | UserError String   -- user-specified error
  | FailError String   -- failing computation
  | NondetError String -- non-deterministic computation
 deriving Eq

instance Show IOError where
  show (IOError     s) = "i/o error: " ++ s
  show (UserError   s) = "user error: " ++ s
  show (FailError   s) = "fail error: " ++ s
  show (NondetError s) = "nondet error: " ++ s

--- A user error value is created by providing a description of the
--- error situation as a string.
userError :: String -> IOError
userError = UserError

--- Raises an I/O exception with a given error value.
ioError :: IOError -> IO _
#ifdef __KICS2__
ioError err = prim_ioError $## err

prim_ioError :: IOError -> IO _
prim_ioError external
#else
ioError err = error (show err)
#endif

--- Catches a possible error or failure during the execution of an
--- I/O action. `catch act errfun` executes the I/O action `act`.
--- If an exception or failure occurs during this I/O action, the
--- function `errfun` is applied to the error value.
catch :: IO a -> (IOError -> IO a) -> IO a
catch external

--- The type synonym for constraints. It is included for backward
--- compatibility and should be no longer used.
type Success = Bool

--- The always satisfiable constraint. It is included for backward
--- compatibility and should be no longer used.
success :: Success
success = True

--- Enforce a Boolean condition to be true.
--- The computation fails if the argument evaluates to `False`.
solve :: Bool -> Bool
solve True = True

--- Solves a constraint as an I/O action.
--- Note: The constraint should be always solvable in a deterministic way.
doSolve :: Bool -> IO ()
doSolve b | b = return ()

--- The equational constraint.
--- `(e1 =:= e2)` is satisfiable if both sides `e1` and `e2` can be
--- reduced to a unifiable data term (i.e., a term without defined
--- function symbols).
#ifdef __PAKCS__
(=:=) :: Data a => a -> a -> Bool
x =:= y = constrEq x y
#elif defined(__CURRY2GO__)
(=:=) :: Data a => a -> a -> Bool
x =:= y = constrEq x y
#else
(=:=) :: a -> a -> Bool
(=:=) external
#endif

--- Internal operation to implement equational constraints.
--- It is used by the strict equality optimizer but should not be used
--- in regular programs.
constrEq :: a -> a -> Bool
#ifdef __PAKCS__
constrEq external
#elif defined(__CURRY2GO__)
constrEq external
#else
constrEq x y = x =:= y
#endif

--- Non-strict equational constraint.
--- This operation is not intended to be used in source programs
--- but it is used to implement
--- [functional patterns](https://doi.org/10.1007/11680093_2).
--- Conceptually, `(e1 =:<= e2)` is satisfiable if `e1` can be evaluated
--- to some pattern (data term) that matches `e2`, i.e., `e2` is
--- an instance of this pattern.
--- The `Data` context is required since the resulting pattern might be
--- non-linear so that it abbreviates some further equational constraints,
--- see [Section 7](https://doi.org/10.1007/978-3-030-46714-2_15).
#ifdef __PAKCS__
(=:<=) :: Data a => a -> a -> Bool
x =:<= y = nonstrictEq x y
#elif defined(__CURRY2GO__)
(=:<=) :: Data a => a -> a -> Bool
x =:<= y = nonstrictEq x y
#else
(=:<=) :: a -> a -> Bool
(=:<=) external
#endif

#ifdef __PAKCS__
nonstrictEq :: a -> a -> Bool
nonstrictEq external
#elif defined(__CURRY2GO__)
nonstrictEq :: a -> a -> Bool
nonstrictEq external
#endif

--- Non-strict equational constraint for linear functional patterns.
--- Thus, it must be ensured that the first argument is always
--- (after evalutation by narrowing) a linear pattern.
--- Experimental and only supported in PAKCS.
(=:<<=) :: Data a => a -> a -> Bool
#ifdef __PAKCS__
x =:<<= y = unifEqLinear x y

-- Internal implementation of `=:<<=`.
unifEqLinear :: a -> a -> Bool
unifEqLinear external

--- Internal operation used by PAKCS to implement `=:<=`.
ifVar :: _ -> a -> a -> a
ifVar external
#else
_ =:<<= _ = error "Prelude.=:<<= not supported!"
#endif

--- Concurrent conjunction.
--- An expression like `(c1 & c2)` is evaluated by evaluating
--- the `c1` and `c2` in a concurrent manner.
(&) :: Bool -> Bool -> Bool
(&) external

--- Conditional expression.
--- An expression like `(c &> e)` is evaluated by evaluating the first
--- argument to `True` and then evaluating `e`.
--- The expression has no value if the condition does not evaluate to `True`.
(&>) :: Bool -> a -> a
True &> x = x

--- Non-deterministic choice _par excellence_.
--- The value of `x ? y` is either `x` or `y`.
(?) :: a -> a -> a
x ? _ = x
_ ? y = y

--- Returns non-deterministically any element of a list.
anyOf :: [a] -> a
anyOf xs = foldr1 (?) xs

--- Evaluates to a fresh free variable.
unknown :: Data a => a
unknown = let x free in x

--- A non-reducible polymorphic function.
--- It is useful to express a failure in a search branch of the execution.
failed :: _
failed external

--- Aborts the execution with an error message.
error :: String -> _
error x = prim_error $## x

prim_error :: String -> _
prim_error external

-- Representation of higher-order applications in FlatCurry.
apply :: (a -> b) -> a -> b
apply external

-- Representation of conditional rules in FlatCurry.
cond :: Bool -> a -> a
cond external

----------------------------------------------------------------
-- Extras used by specific Curry tools.

--- Identity type synonym used to mark deterministic operations.
--- Used by the Curry preprocessor.
type DET a = a

--- Identity function used by the partial evaluator
--- to mark expressions to be partially evaluated.
PEVAL   :: a -> a
PEVAL x = x

----------------------------------------------------------------
types:
Bool Char DET Either FilePath Float IO IOError Int Maybe Ordering ReadS ShowS String Success
unsafe:
safe