A Standard Prelude

In this appendix the entire Haskell prelude is given. It is organized into a root module and three sub-modules. Primitives which are not definable in Haskell, indicated by names starting with prim, are defined in a system dependent manner in module PreludeBuiltin and are not shown here. Instance declarations which simply bind primitives to class methods are omitted. Some of the more verbose instances with obvious functionality have been left out for the sake of brevity.

Declarations for special types such as Integer, (), or (->) are included in the Prelude for completeness even though the declaration may be incomplete or syntacticly invalid.


module Prelude (
    module PreludeList, module PreludeText, module PreludeIO,
    Bool(False, True),
    Maybe(Nothing, Just),
    Either(Left, Right),
    Ordering(LT, EQ, GT),
    Char, String, Int, Integer, Float, Double, IO, Void,
--  List type: []((:), [])
--  Tuple types: (,), (,,), etc.
--  Trivial type: ()
--  Functions: (->)
    Eq((==), (/=)),
    Ord(compare, (<), (<=), (>=), (>), max, min),
    Enum(toEnum, fromEnum, enumFrom, enumFromThen,
         enumFromTo, enumFromThenTo),
    Bounded(minBound, maxBound),
    Eval(seq, strict),
    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),
    Monad((>>=), (>>), return),
    MonadZero(zero),
    MonadPlus((++)),
    Functor(map),
    succ, pred,
    mapM, mapM_, guard, accumulate, sequence, filter, concat, applyM,
    maybe,
    (&&), (||), not, otherwise,
    subtract, even, odd, gcd, lcm, (^), (^^), 
    fromIntegral, fromRealFrac, atan2,
    fst, snd, curry, uncurry, id, const, (.), flip, ($), until,
    asTypeOf, error, undefined ) where

import PreludeBuiltin  -- Contains all `prim' values
import PreludeList
import PreludeText
import PreludeIO
import Ratio(Ratio, Rational, (%), numerator, denominator)

infixr 9  .
infixr 8  ^, ^^, **
infixl 7  *, /, `quot`, `rem`, `div`, `mod`
infixl 6  +, -
infixr 5  ++
infix  4  ==, /=, <, <=, >=, >
infixr 3  &&
infixr 2  ||
infixr 1  >>, >>=
infixr 0  $, `seq`

-- Standard types, classes, instances and related functions

-- Equality and Ordered classes

class  Eq a  where
    (==), (/=)          :: a -> a -> Bool

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

class  (Eq a) => Ord a  where
    compare             :: a -> a -> Ordering
    (<), (<=), (>=), (>):: a -> a -> Bool
    max, min            :: a -> a -> a

-- An instance of Ord should define either compare or <=
-- Using compare can be more efficient for complex types.
    compare x y
            | x == y    = EQ
            | x <= y    = LT
            | otherwise = GT

    x <= y              = compare x y /= GT
    x <  y              = compare x y == LT
    x >= y              = compare x y /= LT
    x >  y              = compare x y == GT

    max x y | x >= y    =  x
            | otherwise =  y
    min x y | x <  y    =  x
            | otherwise =  y

-- Enumeration and Bounded classes

class  (Ord a) => Enum a        where
    toEnum              :: Int -> a
    fromEnum            :: a -> Int
    enumFrom            :: a -> [a]             -- [n..]
    enumFromThen        :: a -> a -> [a]        -- [n,n'..]
    enumFromTo          :: a -> a -> [a]        -- [n..m]
    enumFromThenTo      :: a -> a -> a -> [a]   -- [n,n'..m]

    enumFromTo n m      =  takeWhile (<= m) (enumFrom n)
    enumFromThenTo n n' m
                        =  takeWhile (if n' >= n then (<= m) else (>= m))
                                     (enumFromThen n n')

succ, pred              :: Enum a => a -> a
succ                    =  toEnum . (+1) . fromEnum
pred                    =  toEnum . (subtract 1) . fromEnum

class  Bounded a  where
    minBound, maxBound :: a

-- Numeric classes

class  (Eq a, Show a, Eval a) => Num a  where
    (+), (-), (*)       :: a -> a -> a
    negate              :: a -> a
    abs, signum         :: a -> a
    fromInteger         :: Integer -> a

    x - y               =  x + negate y

class  (Num a, Ord a) => Real a  where
    toRational          ::  a -> Rational

class  (Real a, Enum a) => Integral a  where
    quot, rem, div, mod :: a -> a -> a
    quotRem, divMod     :: a -> a -> (a,a)
    toInteger           :: a -> Integer

    n `quot` d          =  q  where (q,r) = quotRem n d
    n `rem` d           =  r  where (q,r) = quotRem n d
    n `div` d           =  q  where (q,r) = divMod n d
    n `mod` d           =  r  where (q,r) = divMod n d
    divMod n d          =  if signum r == - signum d then (q-1, r+d) else qr
                           where qr@(q,r) = quotRem n d

class  (Num a) => Fractional a  where
    (/)                 :: a -> a -> a
    recip               :: a -> a
    fromRational        :: Rational -> a

    recip x             =  1 / x

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

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

class  (Real a, Fractional a) => RealFrac a  where
    properFraction      :: (Integral b) => a -> (b,a)
    truncate, round     :: (Integral b) => a -> b
    ceiling, 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 signum (abs r - 0.5) of
                                -1 -> n
                                0  -> if even n then n else m
                                1  -> 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

class  (RealFrac a, Floating a) => RealFloat a  where
    floatRadix          :: a -> Integer
    floatDigits         :: a -> Int
    floatRange          :: a -> (Int,Int)
    decodeFloat         :: a -> (Integer,Int)
    encodeFloat         :: Integer -> Int -> a
    exponent            :: a -> Int
    significand         :: a -> a
    scaleFloat          :: Int -> a -> a
    isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE
                        :: a -> Bool

    exponent x          =  if m == 0 then 0 else n + floatDigits x
                           where (m,n) = decodeFloat x

    significand x       =  encodeFloat m (- floatDigits x)
                           where (m,_) = decodeFloat x

    scaleFloat k x      =  encodeFloat m (n+k)
                           where (m,n) = decodeFloat x

-- Numeric functions

subtract        :: (Num a) => a -> a -> a
subtract        =  flip (-)

even, odd       :: (Integral a) => a -> Bool
even n          =  n `rem` 2 == 0
odd             =  not . even

gcd             :: (Integral a) => a -> a -> a
gcd 0 0         =  error "Prelude.gcd: gcd 0 0 is undefined"
gcd x y         =  gcd' (abs x) (abs y)
                   where gcd' x 0  =  x
                         gcd' x y  =  gcd' y (x `rem` y)

lcm             :: (Integral a) => a -> a -> a
lcm _ 0         =  0
lcm 0 _         =  0
lcm x y         =  abs ((x `quot` (gcd x y)) * y)

(^)             :: (Num a, Integral b) => a -> b -> a
x ^ 0           =  1
x ^ n | n > 0   =  f x (n-1) x
                   where f _ 0 y = y
                         f x n y = g x n  where
                                   g x n | even n  = g (x*x) (n `quot` 2)
                                         | otherwise = f x (n-1) (x*y)
_ ^ _           = error "Prelude.^: negative exponent"

(^^)            :: (Fractional a, Integral b) => a -> b -> a
x ^^ n          =  if n >= 0 then x^n else recip (x^(-n))

fromIntegral    :: (Integral a, Num b) => a -> b
fromIntegral    =  fromInteger . toInteger

fromRealFrac    :: (RealFrac a, Fractional b) => a -> b
fromRealFrac    =  fromRational . toRational

atan2           :: (RealFloat a) => a -> a -> a
atan2 y x       =  case (signum y, signum x) of
                        ( 0, 1) ->  0
                        ( 1, 0) ->  pi/2
                        ( 0,-1) ->  pi
                        (-1, 0) -> -pi/2
                        ( _, 1) ->  atan (y/x)
                        ( _,-1) ->  atan (y/x) + pi
                        ( 0, 0) ->  error "Prelude.atan2: atan2 of origin"

-- Monadic classes

class  Functor f  where
    map         :: (a -> b) -> f a -> f b

class  Monad m  where
    (>>=)       :: m a -> (a -> m b) -> m b
    (>>)        :: m a -> m b -> m b
    return      :: a -> m a

    m >> k      =  m >>= \_ -> k

class  (Monad m) => MonadZero m  where
    zero        :: m a

class  (MonadZero m) => MonadPlus m where
   (++)         :: m a -> m a -> m a

accumulate      :: Monad m => [m a] -> m [a] 
accumulate      =  foldr mcons (return [])
                   where mcons p q = p >>= \x -> q >>= \y -> return (x:y)

sequence        :: Monad m => [m a] -> m () 
sequence        =  foldr (>>) (return ())

mapM            :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as       =  accumulate (map f as)

mapM_           :: Monad m => (a -> m b) -> [a] -> m ()
mapM_ f as      =  sequence (map f as)

guard           :: MonadZero m => Bool -> m ()
guard p         =  if p then return () else zero

-- This subsumes the list-based filter function.

filter          :: MonadZero m => (a -> Bool) -> m a -> m a
filter p        =  applyM (\x -> if p x then return x else zero)

-- This subsumes the list-based concat function.

concat          :: MonadPlus m => [m a] -> m a
concat          =  foldr (++) zero

applyM          :: Monad m => (a -> m b) -> m a -> m b
applyM f x      =  x >>= f

-- Eval Class

class Eval a where
   seq         :: a -> a -> b
   strict      :: (a -> b) -> a -> b
   strict f x  =  x `seq` f x

-- Trivial type

data  ()  =  ()  deriving (Eq, Ord, Enum, Bounded)

-- Function type

data a -> b  -- No constructor for functions is exported.

-- Empty type

data Void      -- No constructor for Void is exported.  Import/Export
               -- lists must use Void instead of Void(..) or Void()

-- Boolean type

data  Bool  =  False | True     deriving (Eq, Ord, Enum, Read, Show, Bounded)

-- Boolean functions

(&&), (||)              :: Bool -> Bool -> Bool
True  && x              =  x
False && _              =  False
True  || _              =  True
False || x              =  x

not                     :: Bool -> Bool
not True                =  False
not False               =  True

otherwise               :: Bool
otherwise               =  True

-- Character type

data Char = ... 'a' | 'b' ... -- 265 ISO values

instance  Eq Char  where
    c == c'             =  fromEnum c == fromEnum c'

instance  Ord Char  where
    c <= c'             =  fromEnum c <= fromEnum c'

instance  Enum Char  where
    toEnum              =  primIntToChar
    fromEnum            =  primCharToInt
    enumFrom c          =  map toEnum [fromEnum c .. fromEnum (maxBound::Char)]
    enumFromThen c c'   =  map toEnum [fromEnum c,
                                       fromEnum c' .. fromEnum lastChar]
                           where lastChar :: Char
                                 lastChar | c' < c    = minBound
                                          | otherwise = maxBound

instance  Bounded Char  where
    minBound            =  '\0'
    maxBound            =  '\255'

type  String = [Char]

-- Maybe type

data  Maybe a  =  Nothing | Just a      deriving (Eq, Ord, Read, Show)

maybe                   :: b -> (a -> b) -> Maybe a -> b
maybe n f Nothing       =  n
maybe n f (Just x)      =  f x

instance  Functor Maybe  where
    map f Nothing       = Nothing
    map f (Just a)      = Just (f x)

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

instance  MonadZero Maybe  where
    zero                = Nothing

instance  MonadPlus Maybe  where
    Nothing ++ ys       = ys
    xs      ++ ys       = xs

-- Either type

data  Either a b  =  Left a | Right b   deriving (Eq, Ord, Read, Show)

either                  :: (a -> c) -> (b -> c) -> Either a b -> c
either f g (Left x)     =  f x
either f g (Right y)    =  g y

-- IO type

data  IO a  -- abstract

instance  Functor IO where
   map f x              = x >>= (return . f)

instance  Monad IO  where ...

-- Ordering type

data Ordering = LT | EQ | GT  deriving (Eq, Ord, Enum, Read, Show, Bounded)

-- Standard numeric types.  The data declarations for these types cannot
-- be expressed directly in Haskell since the constructor lists would be
-- far too large.

data Int  =  minBound ... -1 | 0 | 1 ... maxBound
instance  Eq       Int  where ...
instance  Ord      Int  where ...
instance  Num      Int  where ...
instance  Real     Int  where ...
instance  Integral Int  where ...
instance  Enum     Int  where ...
instance  Bounded  Int  where ...

data Integer = ... -1 | 0 | 1 ...
instance  Eq       Integer  where ...
instance  Ord      Integer  where ...
instance  Num      Integer  where ...
instance  Real     Integer  where ...
instance  Integral Integer  where ...
instance  Enum     Integer  where ...

data Float
instance  Eq         Float  where ...
instance  Ord        Float  where ...
instance  Num        Float  where ...
instance  Real       Float  where ...
instance  Fractional Float  where ...
instance  Floating   Float  where ...
instance  RealFrac   Float  where ...
instance  RealFloat  Float  where ...

data Double
instance  Eq         Double  where ...
instance  Ord        Double  where ...
instance  Num        Double  where ...
instance  Real       Double  where ...
instance  Fractional Double  where ...
instance  Floating   Double  where ...
instance  RealFrac   Double  where ...
instance  RealFloat  Double  where ...

-- The Enum instances for Floats and Doubles are slightly unusual.
-- The `toEnum' function truncates numbers to Int.  The definitions
-- of enumFrom and enumFromThen allow floats to be used in arithmetic
-- series: [0,0.1 .. 1.0].  However, roundoff errors make these somewhat
-- dubious.  This example may have either 10 or 11 elements, depending on
-- how 0.1 is represented.

instance  Enum Float  where
    toEnum              =  fromIntegral
    fromEnum            =  fromInteger . truncate   -- may overflow
    enumFrom            =  numericEnumFrom
    enumFromThen        =  numericEnumFromThen

instance  Enum Double  where
    toEnum              =  fromIntegral
    fromEnum            =  fromInteger . truncate   -- may overflow
    enumFrom            =  numericEnumFrom
    enumFromThen        =  numericEnumFromThen

numericEnumFrom         :: (Real a) => a -> [a]
numericEnumFromThen     :: (Real a) => a -> a -> [a]
numericEnumFrom         =  iterate (+1)
numericEnumFromThen n m =  iterate (+(m-n)) n

-- Lists

data  [a]  =  [] | a : [a]  deriving (Eq, Ord)

instance Functor [] where
    map f []             =  []
    map f (x:xs)         =  f x : map f xs

instance  Monad []  where
    m >>= k             = concat (map k m)
    return x            = [x]

instance  MonadZero []  where
    zero                = []

instance  MonadPlus []  where
    xs ++ ys            =  foldr (:) ys xs

-- Tuples

data  (a,b)   =  (a,b)   deriving (Eq, Ord, Bounded)
data  (a,b,c) =  (a,b,c) deriving (Eq, Ord, Bounded)

-- component projections for pairs:
-- (NB: not provided for triples, quadruples, etc.)
fst                     :: (a,b) -> a
fst (x,y)               =  x

snd                     :: (a,b) -> b
snd (x,y)               =  y

-- curry converts an uncurried function to a curried function;
-- uncurry converts a curried function to a function on pairs.
curry                   :: ((a, b) -> c) -> a -> b -> c
curry f x y             =  f (x, y)

uncurry                 :: (a -> b -> c) -> ((a, b) -> c)
uncurry f p             =  f (fst p) (snd p)

-- Functions

-- Standard value bindings

-- identity function
id                      :: a -> a
id x                    =  x

-- constant function
const                   :: a -> b -> a
const x _               =  x

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

-- flip f  takes its (first) two arguments in the reverse order of f.
flip                    :: (a -> b -> c) -> b -> a -> c
flip f x y              =  f y x

-- right-associating infix application operator (useful in continuation-
-- passing style)
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

-- until p f  yields the result of applying f until p holds.
until                   :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x       =  x
            | otherwise =  until p f (f 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

-- error stops execution and displays an error message

error                   :: String -> a
error                   =  primError

-- It is expected that compilers will recognize this and insert error
-- messages which are more appropriate to the context in which undefined 
-- appears. 

undefined               :: a
undefined               =  error "Prelude.undefined"

A.1 Prelude PreludeList


-- Standard list functions

module PreludeList(
   head, last, tail, init, null, length, (!!),
   foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1,
   iterate, repeat, replicate, cycle,
   take, drop, splitAt, takeWhile, dropWhile, span, break,
   lines, words, unlines, unwords, reverse, and, or,
   any, all, elem, notElem, lookup,
   sum, product, maximum, minimum, concatMap, 
   zip, zip3, zipWith, zipWith3, unzip, unzip3)
  where

import qualified Char(isSpace)

infixl 9  !!
infix  4 `elem`, `notElem`

-- head and tail extract the first element and remaining elements,
-- respectively, of a list, which must be non-empty.  last and init
-- are the dual functions working from the end of a finite list,
-- rather than the beginning.

head                    :: [a] -> a
head (x:_)              =  x
head []                 =  error "PreludeList.head: empty list"

last                    :: [a] -> a
last [x]                =  x
last (_:xs)             =  last xs
last []                 =  error "PreludeList.last: empty list"

tail                    :: [a] -> [a]
tail (_:xs)             =  xs
tail []                 =  error "PreludeList.tail: empty list"

init                    :: [a] -> [a]
init [x]                =  []
init (x:xs)             =  x : init xs
init []                 =  error "PreludeList.init: empty list"

null                    :: [a] -> Bool
null []                 =  True
null (_:_)              =  False

-- length returns the length of a finite list as an Int; it is an instance
-- of the more general genericLength, the result type of which may be
-- any kind of number.
length                  :: [a] -> Int
length []               =  0
length (_:l)            =  1 + length l

-- List index (subscript) operator, 0-origin
(!!)                    :: [a] -> Int -> a
(x:_)  !! 0             =  x
(_:xs) !! n | n > 0     =  xs !! (n-1)
(_:_)  !! _             =  error "PreludeList.!!: negative index"
[]     !! _             =  error "PreludeList.!!: index too large"

-- foldl, applied to a binary operator, a starting value (typically the
-- left-identity of the operator), and a list, reduces the list using
-- the binary operator, from left to right:
--  foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
-- foldl1 is a variant that has no starting value argument, and  thus must
-- be applied to non-empty lists.  scanl is similar to foldl, but returns
-- a list of successive reduced values from the left:
--      scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...]
-- Note that  last (scanl f z xs) == foldl f z xs.
-- scanl1 is similar, again without the starting element:
--      scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]

foldl                   :: (a -> b -> a) -> a -> [b] -> a
foldl f z []            =  z
foldl f z (x:xs)        =  foldl f (f z x) xs

foldl1                  :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs)         =  foldl f x xs
foldl1 _ []             =  error "PreludeList.foldl1: empty list"

scanl                   :: (a -> b -> a) -> a -> [b] -> [a]
scanl f q xs            =  q : (case xs of
                                []   -> []
                                x:xs -> scanl f (f q x) xs)

scanl1                  :: (a -> a -> a) -> [a] -> [a]
scanl1 f (x:xs)         =  scanl f x xs
scanl1 _ []             =  error "PreludeList.scanl1: empty list"

-- foldr, foldr1, scanr, and scanr1 are the right-to-left duals of the
-- above functions.

foldr                   :: (a -> b -> b) -> b -> [a] -> b
foldr f z []            =  z
foldr f z (x:xs)        =  f x (foldr f z xs)

foldr1                  :: (a -> a -> a) -> [a] -> a
foldr1 f [x]            =  x
foldr1 f (x:xs)         =  f x (foldr1 f xs)
foldr1 _ []             =  error "PreludeList.foldr1: empty list"

scanr                   :: (a -> b -> b) -> b -> [a] -> [b]
scanr f q0 []           =  [q0]
scanr f q0 (x:xs)       =  f x q : qs
                           where qs@(q:_) = scanr f q0 xs 

scanr1                  :: (a -> a -> a) -> [a] -> [a]
scanr1 f  [x]           =  [x]
scanr1 f  (x:xs)        =  f x q : qs
                           where qs@(q:_) = scanr1 f xs 
scanr1 _ []             =  error "PreludeList.scanr1: empty list"

-- iterate f x returns an infinite list of repeated applications of f to x:
-- iterate f x == [x, f x, f (f x), ...]
iterate                 :: (a -> a) -> a -> [a]
iterate f x             =  x : iterate f (f x)

-- repeat x is an infinite list, with x the value of every element.
repeat                  :: a -> [a]
repeat x                =  xs where xs = x:xs

-- replicate n x is a list of length n with x the value of every element
replicate               :: Int -> a -> [a]
replicate n x           =  take n (repeat x)

-- cycle ties a finite list into a circular one, or equivalently,
-- the infinite repetition of the original list.  It is the identity
-- on infinite lists.

cycle                   :: [a] -> [a]
cycle xs                =  xs' where xs' = xs ++ xs'

-- take n, applied to a list xs, returns the prefix of xs of length n,
-- or xs itself if n > length xs.  drop n xs returns the suffix of xs
-- after the first n elements, or [] if n > length xs.  splitAt n xs
-- is equivalent to (take n xs, drop n xs).

take                   :: Int -> [a] -> [a]
take 0 _               =  []
take _ []              =  []
take n (x:xs) | n > 0  =  x : take (n-1) xs
take _     _           =  error "PreludeList.take: negative argument"

drop                   :: Int -> [a] -> [a]
drop 0 xs              =  xs
drop _ []              =  []
drop n (_:xs) | n > 0  =  drop (n-1) xs
drop _     _           =  error "PreludeList.drop: negative argument"

splitAt                   :: Int -> [a] -> ([a],[a])
splitAt 0 xs              =  ([],xs)
splitAt _ []              =  ([],[])
splitAt n (x:xs) | n > 0  =  (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs
splitAt _     _           =  error "PreludeList.splitAt: negative argument"

-- takeWhile, applied to a predicate p and a list xs, returns the longest
-- prefix (possibly empty) of xs of elements that satisfy p.  dropWhile p xs
-- returns the remaining suffix.  Span p xs is equivalent to 
-- (takeWhile p xs, dropWhile p xs), while break p uses the negation of p.

takeWhile               :: (a -> Bool) -> [a] -> [a]
takeWhile p []          =  []
takeWhile p (x:xs) 
            | p x       =  x : takeWhile p xs
            | otherwise =  []

dropWhile               :: (a -> Bool) -> [a] -> [a]
dropWhile p []          =  []
dropWhile p xs@(x:xs')
            | p x       =  dropWhile p xs'
            | otherwise =  xs

span, break             :: (a -> Bool) -> [a] -> ([a],[a])
span p []               =  ([],[])
span p xs@(x:xs') 
            | p x       =  (x:xs',xs'') where (xs',xs'') = span p xs
            | otherwise =  (xs,[])
break p                 =  span (not . p)

-- lines breaks a string up into a list of strings at newline characters.
-- The resulting strings do not contain newlines.  Similary, words
-- breaks a string up into a list of words, which were delimited by
-- white space.  unlines and unwords are the inverse operations.
-- unlines joins lines with terminating newlines, and unwords joins
-- words with separating spaces.

lines                   :: String -> [String]
lines ""                =  []
lines s                 =  let (l, s') = break (== '\n') s
                           in  l : case s' of
                                        []      -> []
                                        (_:s'') -> lines s''

words                   :: String -> [String]
words s                 =  case dropWhile Char.isSpace s of
                                "" -> []
                                s' -> w : words s''
                                      where (w, s'') = 
                                        break Char.isSpace s'

unlines                 :: [String] -> String
unlines                 =  concatMap (++ "\n")

unwords                 :: [String] -> String
unwords []              =  ""
unwords ws              =  foldr1 (\w s -> w ++ ' ':s) ws

-- reverse xs returns the elements of xs in reverse order.  xs must be finite.
reverse                 :: [a] -> [a]
reverse                 =  foldl (flip (:)) []

-- and returns the conjunction of a Boolean list.  For the result to be
-- True, the list must be finite; False, however, results from a False
-- value at a finite index of a finite or infinite list.  or is the
-- disjunctive dual of and.
and, or                 :: [Bool] -> Bool
and                     =  foldr (&&) True
or                      =  foldr (||) False

-- Applied to a predicate and a list, any determines if any element
-- of the list satisfies the predicate.  Similarly, for all.
any, all                :: (a -> Bool) -> [a] -> Bool
any p                   =  or . map p
all p                   =  and . map p

-- elem is the list membership predicate, usually written in infix form,
-- e.g., x `elem` xs.  notElem is the negation.
elem, notElem           :: (Eq a) => a -> [a] -> Bool
elem x                  =  any (== x)
notElem x               =  all (not . (/= x))

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

-- sum and product compute the sum or product of a finite list of numbers.
sum, product            :: (Num a) => [a] -> a
sum                     =  foldl (+) 0  
product                 =  foldl (*) 1

-- maximum and minimum return the maximum or minimum value from a list,
-- which must be non-empty, finite, and of an ordered type.
maximum, minimum        :: (Ord a) => [a] -> a
maximum []              =  error "PreludeList.maximum: empty list"
maximum xs              =  foldl1 max xs

minimum []              =  error "PreludeList.minimum: empty list"
minimum xs              =  foldl1 min xs

concatMap               :: (a -> [b]) -> [a] -> [b]
concatMap f             =  concat . map f

-- zip takes two lists and returns a list of corresponding pairs.  If one
-- input list is short, excess elements of the longer list are discarded.
-- zip3 takes three lists and returns a list of triples.  Zips for larger
-- tuples are in the List library

zip                     :: [a] -> [b] -> [(a,b)]
zip                     =  zipWith (,)

zip3                    :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3                    =  zipWith3 (,,)

-- The zipWith family generalises the zip family by zipping with the
-- function given as the first argument, instead of a tupling function.
-- For example, zipWith (+) is applied to two lists to produce the list
-- of corresponding sums.

zipWith                 :: (a->b->c) -> [a]->[b]->[c]
zipWith z (a:as) (b:bs) =  z a b : zipWith z as bs
zipWith _ _ _           =  []

zipWith3                :: (a->b->c->d) -> [a]->[b]->[c]->[d]
zipWith3 z (a:as) (b:bs) (c:cs)
                        =  z a b c : zipWith3 z as bs cs
zipWith3 _ _ _ _        =  []

-- unzip transforms a list of pairs into a pair of lists.  

unzip                   :: [(a,b)] -> ([a],[b])
unzip                   =  foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])

unzip3                  :: [(a,b,c)] -> ([a],[b],[c])
unzip3                  =  foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
                                 ([],[],[])

A.2 Prelude PreludeText


module  PreludeText (
        ReadS, ShowS,
        Read(readsPrec, readList),
        Show(showsPrec, showList),
        reads, shows, show, read, lex,
        showChar, showString, readParen, showParen ) where

-- The omitted instances can be implemented in standard Haskell but
-- they have been omitted for the sake of brevity

import Char( isSpace, isAlpha, isDigit, isAlphanum, isHexDigit )

type  ReadS a   = String -> [(a,String)]
type  ShowS     = String -> String

class  Read a  where
    readsPrec :: Int -> ReadS a
    readList  :: ReadS [a]

    readList    = 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]

class  Show a  where
    showsPrec :: Int -> a -> ShowS
    showList  :: [a] -> ShowS

    showList [] = showString "[]"
    showList (x:xs)
                = showChar '[' . shows x . showl xs
                  where showl []     = showChar ']'
                        showl (x:xs) = showString ", " . shows x . showl xs

reads           :: (Read a) => ReadS a
reads           =  readsPrec 0

shows           :: (Show a) => a -> ShowS
shows           =  showsPrec 0

read            :: (Read a) => String -> a
read s          =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                        [x] -> x
                        []  -> error "PreludeText.read: no parse"
                        _   -> error "PreludeText.read: ambiguous parse"

show            :: (Show a) => a -> String
show x          =  shows x ""

showChar        :: Char -> ShowS
showChar        =  (:)

showString      :: String -> ShowS
showString      =  (++)

showParen       :: Bool -> ShowS -> ShowS
showParen b p   =  if b then showChar '(' . p . showChar ')' else p

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    ]

-- This lexer is not completely faithful to the Haskell lexical syntax.
-- Current limitations:
--    Qualified names are not handled properly
--    A `--' does not terminate a symbol
--    Octal and hexidecimal numerics are not recognized as a single token

lex                   :: ReadS String
lex ""                = [("","")]
lex (c:s) | isSpace c = lex (dropWhile isSpace s)
lex ('\'':s)          = [('\'':ch++"'", t) | (ch,'\'':t)  <- lexLitChar s,
                                              ch /= "'"                ]
lex ('"':s)           = [('"':str, t)      | (str,t) <- lexString s]
                        where
                        lexString ('"':s) = [("\"",s)]
                        lexString s = [(ch++str, u)
                                              | (ch,t)  <- lexStrItem s,
                                                (str,u) <- lexString t  ]

                        lexStrItem ('\\':'&':s) = [("\\&",s)]
                        lexStrItem ('\\':c:s) | isSpace c
                            = [("\\&",t) | '\\':t <- [dropWhile isSpace s]]
                        lexStrItem s            = lexLitChar s

lex (c:s) | isSingle c = [([c],s)]
          | isSym c    = [(c:sym,t)       | (sym,t) <- [span isSym s]]
          | isAlpha c  = [(c:nam,t)       | (nam,t) <- [span isIdChar s]]
          | isDigit c  = [(c:ds++fe,t)    | (ds,s)  <- [span isDigit s],
                                            (fe,t)  <- lexFracExp s     ]
          | otherwise  = []    -- bad character
             where
              isSingle c =  c `elem` ",;()[]{}_`"
              isSym c    =  c `elem` "!@#$%&*+./<=>?\\^|:-~"
              isIdChar c =  isAlphanum c || c `elem` "_'"

              lexFracExp ('.':s) = [('.':ds++e,u) | (ds,t) <- lexDigits s,
                                                    (e,u)  <- lexExp t]
              lexFracExp s       = [("",s)]

              lexExp (e:s) | e `elem` "eE"
                       = [(e:c:ds,u) | (c:t)  <- [s], c `elem` "+-",
                                                 (ds,u) <- lexDigits t] ++
                         [(e:ds,t)   | (ds,t) <- lexDigits s]
              lexExp s = [("",s)]

lexDigits               :: ReadS String 
lexDigits               =  nonnull isDigit

nonnull                 :: (Char -> Bool) -> ReadS String
nonnull p s             =  [(cs,t) | (cs@(_:_),t) <- [span p s]]

lexLitChar              :: ReadS String
lexLitChar ('\\':s)     =  [('\\':esc, t) | (esc,t) <- lexEsc s]
        where
        lexEsc (c:s)     | c `elem` "abfnrtv\\\"'" = [([c],s)]
        lexEsc s@(d:_)   | isDigit d               = lexDigits s
        lexEsc _                                   = []
lexLitChar (c:s)        =  [([c],s)]
lexLitChar ""           =  []

instance  Show Int  where ...
instance  Read Int  where ...

instance  Show Integer  where ...
instance  Read Integer  where ...

instance  Show Float  where ...
instance  Read Float  where ...

instance  Show Double  where ...
instance  Read Double  where ...

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

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

instance  Show Char  where ...
instance  Read Char  where ...

instance  (Show a) => Show [a]  where
    showsPrec p         = showList

instance  (Read a) => Read [a]  where
    readsPrec p         = readList

-- Tuples

instance  (Show a, Show b) => Show (a,b)  where
    showsPrec p (x,y) = showChar '(' . shows x . showChar ',' .
                                       shows y . showChar ')'

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

-- et cetera

-- Functions

instance  Show (a->b)  where
    showsPrec p f  =  showString "<<function>>"

instance  Show (IO a)  where
    showsPrec p f  =  showString "<<IO action>>"

A.3 Prelude PreludeIO


module PreludeIO (
      FilePath, IOError, fail, userError, catch,
      putChar, putStr, putStrLn, print,
      getChar, getLine, getContents, interact,
      readFile, writeFile, appendFile, readIO, readLn
    ) where

import PreludeBuiltin

type FilePath   =  String

data IOError    -- The internals of this type are system dependant

instance Show IOError where ...
instance Eq IOError where ...

fail            ::  IOError -> IO a 
fail            =   primFail

userError       ::  String  -> IOError
userError       =   primUserError

catch           ::  IO a    -> (IOError -> IO a) -> IO a 
catch           =   primCatch

putChar         :: Char -> IO ()
putChar         =  primPutChar

putStr          :: String -> IO ()
putStr s        =  mapM_ s putChar

putStrLn        :: String -> IO ()
putStrLn s      =  do putStr s
                      putStr "\n"

print           :: Show a => IO ()
print x         =  putStrLn (show x)

getChar         :: IO Char
getChar         =  primGetChar

getLine         :: IO String
getLine         =  do c <- getChar
                      if c == '\n' then return "" else 
                         do s <- getLine
                            return (c:s)

getContents     :: IO String
getContents     =  primGetContents

interact        ::  (String -> String) -> IO ()
interact f      =   do s <- getContents
                       putStr (f s)

readFile        :: FilePath -> IO String
readFile        =  primReadFile

writeFile       :: FilePath -> String -> IO ()
writeFile       =  primWriteFile

appendFile      :: FilePath -> String -> IO ()
appendFile      =  primAppendFile

readIO          :: Read a => String -> IO a
  -- raises an exception instead of an error
readIO s        =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                        [x] -> return x
                        []  -> fail (userError "PreludeIO.readIO: no parse")
                        _   -> fail (userError 
                                      "PreludeIO.readIO: ambiguous parse")

readLn          :: Read a => IO a
readLn          =  do l <- getLine
                      r <- readIO l
                      return r

Next section: Syntax
The Haskell 1.3 Report