----------------------------------------------------------------------------
--- The standard prelude of Curry.
--- All top-level functions defined in this module
--- are always available in any Curry program.
----------------------------------------------------------------------------
module Prelude where
-- Lines beginning with "--++" are part of the prelude
-- but cannot parsed by the compiler
-- Infix operator declarations:
infixl 9 !!
infixr 9 .
infixl 7 *, *^, `div`, `mod`
infixl 6 +, +^, -, -^
-- infixr 5 : -- declared together with list
infixr 5 ++
infix 4 =:=, ==, ===, /=, <, >, <=, >=, =:<=, <^, <=^, >^, >=^
infix 4 `elem`, `notElem`
infixr 3 &&
infixr 2 ||
infixl 1 >>, >>=
infixr 0 $, $!, $!!, $#, $##, `seq`, &, &>, ?
-- external base types for numbers and characters
data Float
data Char
type String = [Char]
-- Some standard combinators:
--- 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
--- 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)
--- 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 head normal form.
--- Suspends until the result is bound to a non-variable term.
($#) :: (a->b) -> a -> b
($#) external
--- Right-associative application with strict evaluation of its argument
--- to ground normal form.
--- Suspends until the result is bound to a non-variable term.
($##) :: (a->b) -> a -> b
($##) 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 = (ensureList $#)
where ensureList [] = []
ensureList (x:xs) = x : ensureSpine xs
--- Evaluates the first argument to head normal form (which could also
--- be a free variable) and returns the second argument.
seq :: _ -> a -> a
seq x y = (const y) $! x
--- Aborts the execution with an error message.
error :: String -> _
error s = prim_error $## s
prim_error :: String -> _
prim_error external
--- A non-reducible polymorphic function.
--- It is useful to express a failure in a search branch of the execution.
failed :: _
failed external
-- Boolean values
data Bool = False | True
--- 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.
if_then_else :: Bool -> a -> a -> a
if_then_else b t f = case b of True -> t
False -> f
--- Ordering type. Useful as a result of comparison functions.
data Ordering = LT | EQ | GT
isLT LT = True
isLT GT = False
isLT EQ = False
isGT LT = False
isGT GT = True
isGT EQ = False
isEQ LT = False
isEQ GT = False
isEQ EQ = True
{-compare :: Int -> Int -> Ordering
compare x y | (prim_Int_le $# x) $# y = LT
| (prim_Int_le $# y) $# x = GT
| otherwise = EQ -}
compare :: Int -> Int -> Ordering
compare Zero Zero = EQ
compare Zero (Pos _) = LT
compare Zero (Neg _) = GT
compare (Pos _) Zero = GT
compare (Pos x) (Pos y) = cmpNat x y
compare (Pos _) (Neg _) = GT
compare (Neg _) Zero = LT
compare (Neg _) (Pos _) = LT
compare (Neg x) (Neg y) = cmpNat y x
{-
compare x y = compareData [toNumData x] [toNumData y]
where
compareData :: [NumData] -> [NumData] -> Ordering
compareData [] [] = EQ
compareData (NumData xi xts:xs) (NumData yi yts:ys)
| int_le xi yi = LT
| int_le yi xi = GT
| otherwise = compareData (xts++xs) (yts++ys)
-}
--- Less-than on ground data terms.
(<) :: Int -> Int -> Bool
x < y = compare x y == LT
--- Greater-than on ground data terms.
(>) :: Int -> Int -> Bool
x > y = compare x y == GT
--- Less-or-equal on ground data terms.
(<=) :: Int -> Int -> Bool
x <= y = compare x y /= GT
--- Greater-or-equal on ground data terms.
(>=) :: Int -> Int -> Bool
x >= y = compare x y /= LT
--- Maximum of ground data terms.
max :: Int -> Int -> Int
max x y = case compare x y of
LT -> y
_ -> x
--- Minimum of ground data terms
min :: Int -> Int -> Int
min x y = case compare x y of
GT -> y
_ -> x
--- Equality on finite ground data terms.
(==) :: a -> a -> Bool
(==) external
--- Disequality.
(/=) :: a -> a -> Bool
x /= y = not (x==y)
-- Pairs
--++ data (a,b) = (a,b)
--- 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
-- Unit type
--++ data () = ()
-- Lists
--++ data [a] = [] | a : [a]
--- 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)
--- Map 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. Thus,
--- foldl f z [x1,x2,...,xn] = (...((z `f` x1) `f` x2) ...) `f` xn
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. Thus,
--- foldr f z [x1,x2,...,xn] = (x1 `f` (x2 `f` ... (xn `f` z)...))
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 (x1:x2:xs) = f x1 (foldr1 f (x2: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 l = foldr (++) [] l
--- 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 (Neg _) _ = []
take Zero _ = []
take (Pos _) [] = []
take (Pos n) (x:xs) = x : take (Pos n-1) xs
--- Returns suffix without first n elements.
drop :: Int -> [a] -> [a]
drop n l = if n<=0 then l else dropp n l
where dropp _ [] = []
dropp m (_:xs) = drop (m-1) xs
--- (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)
--- 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 (x:xs) = let (l,xs_l) = splitline (x:xs) in l : lines xs_l
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 ls = concatMap (++"\n") ls
--- 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
where
isSpace c = c == ' ' || c == '\t' || c == '\n' || c == '\r'
--- Concatenates a list of strings with a blank between two strings.
unwords :: [String] -> String
unwords ws = if ws==[] then []
else foldr1 (\w s -> w ++ ' ':s) ws
--- 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 :: a -> [a] -> Bool
elem x = any (x==)
--- Not element of a list?
notElem :: a -> [a] -> Bool
notElem x = all (x/=)
--- Looks up a key in an association list.
lookup :: a -> [(a,b)] -> Maybe b
lookup _ [] = Nothing
lookup k ((x,y):xys)
| k==x = Just y
| otherwise = lookup k xys
--- Generates an infinite sequence of ascending integers.
enumFrom :: Int -> [Int] -- [n..]
enumFrom n = n : enumFrom (n+1)
--- Generates an infinite sequence of integers with a particular in/decrement.
enumFromThen :: Int -> Int -> [Int] -- [n1,n2..]
enumFromThen n1 n2 = iterate ((n2-n1)+) n1
--- Generates a sequence of ascending integers.
enumFromTo :: Int -> Int -> [Int] -- [n..m]
enumFromTo n m = if n>m then [] else n : enumFromTo (n+1) m
--- Generates a sequence of integers with a particular in/decrement.
enumFromThenTo :: Int -> Int -> Int -> [Int] -- [n1,n2..m]
enumFromThenTo n1 n2 m = takeWhile p (enumFromThen n1 n2)
where p x | n2 >= n1 = (x <= m)
| otherwise = (x >= m)
--- Converts a character into its ASCII value.
ord :: Char -> Int
ord c = prim_ord $## c
prim_ord :: Char -> Int
prim_ord external
--- Converts an ASCII value into a character.
chr :: Int -> Char
chr i = prim_chr $## i
prim_chr :: Int -> Char
prim_chr external
-- Natural numbers
data Nat = IHi | O Nat | I Nat
succ :: Nat -> Nat
succ (O bs) = I bs
succ (I bs) = O (succ bs)
succ IHi = O IHi
(+^) :: Nat -> Nat -> Nat
O x +^ O y = O (x +^ y)
O x +^ I y = I (x +^ y)
O x +^ IHi = I x
I x +^ O y = I (x +^ y)
I x +^ I y = O (succ x +^ y)
I x +^ IHi = O (succ x)
IHi +^ y = succ y
cmpNat :: Nat -> Nat -> Ordering
cmpNat IHi IHi = EQ
cmpNat IHi (O _) = LT
cmpNat IHi (I _) = LT
cmpNat (O _) IHi = GT
cmpNat (I _) IHi = GT
cmpNat (O x) (O y) = cmpNat x y
cmpNat (I x) (I y) = cmpNat x y
cmpNat (O x) (I y) = cmpNatLT x y
cmpNat (I x) (O y) = cmpNatGT x y
cmpNatLT :: Nat -> Nat -> Ordering
cmpNatLT IHi _ = LT
cmpNatLT (O _) IHi = GT
cmpNatLT (I _) IHi = GT
cmpNatLT (O x) (O y) = cmpNatLT x y
cmpNatLT (I x) (I y) = cmpNatLT x y
cmpNatLT (O x) (I y) = cmpNatLT x y
cmpNatLT (I x) (O y) = cmpNatGT x y
cmpNatGT :: Nat -> Nat -> Ordering
cmpNatGT _ IHi = GT
cmpNatGT IHi (O _) = LT
cmpNatGT IHi (I _) = LT
cmpNatGT (O x) (O y) = cmpNatGT x y
cmpNatGT (I x) (I y) = cmpNatGT x y
cmpNatGT (O x) (I y) = cmpNatLT x y
cmpNatGT (I x) (O y) = cmpNatGT x y
(<^), (>^), (<=^), (>=^) :: Nat -> Nat -> Bool
x <^ y = isLT (cmpNat x y)
x >^ y = isGT (cmpNat x y)
x <=^ y = not (isGT (cmpNat x y))
x >=^ y = not (isLT (cmpNat x y))
(*^) :: Nat -> Nat -> Nat
IHi *^ y = y
I x *^ y = O (y *^ x) +^ y
O x *^ y = O (x *^ y)
pred :: Nat -> Nat
pred (O IHi) = IHi
pred (O x@(O _)) = I (pred x)
pred (O (I x)) = I (O x)
pred (I x) = O x
-- Integers
data Int = Neg Nat | Zero | Pos Nat
-- basic operations (+1), (-1), (*2)
inc, dec, mult2 :: Int -> Int
inc Zero = Pos IHi
inc (Pos n) = Pos (succ n)
inc (Neg IHi) = Zero
inc (Neg (O n)) = Neg (pred (O n))
inc (Neg (I n)) = Neg (O n)
dec Zero = Neg IHi
dec (Neg n) = Neg (succ n)
dec (Pos IHi) = Zero
dec (Pos (O n)) = Pos (pred (O n))
dec (Pos (I n)) = Pos (O n)
mult2 (Pos n) = Pos (O n)
mult2 Zero = Zero
mult2 (Neg n) = Neg (O n)
(-^) :: Nat -> Nat -> Int
IHi -^ y = inc (Neg y) -- 1-n = 1+(-n)
O x -^ IHi = Pos (pred (O x))
O x -^ O y = mult2 (x -^ y)
O x -^ I y = dec (mult2 (x -^ y))
I x -^ IHi = Pos (O x)
I x -^ O y = inc (mult2 (x -^ y)) -- 2*n+1 - 2*m = 1+2*(n-m)
I x -^ I y = mult2 (x -^ y) -- 2*n+1 - (2*m+1) = 2*(n-m)
div2 :: Nat -> Nat
div2 (O x) = x
div2 (I x) = x
mod2 :: Nat -> Int
mod2 IHi = Pos IHi
mod2 (O _) = Zero
mod2 (I _) = Pos IHi
divmodNat :: Nat -> Nat -> (Int,Int)
divmodNat x y
| y==IHi = (Pos x,Zero)
| otherwise = case cmpNat x y of
EQ -> (Pos IHi,Zero)
LT -> (Zero, Pos x)
GT -> case divmodNat (div2 x) y of
(Zero,_) -> (Pos IHi,x -^ y)
(Pos d,Zero) -> (Pos (O d),mod2 x)
(Pos d,Pos m) -> case divmodNat (shift x m) y of
(Zero,m') -> (Pos (O d),m')
(Pos d',m') -> (Pos (O d +^ d'),m')
where
shift (O _) n = O n
shift (I _) n = I n
--- Adds two integers.
(+) :: Int -> Int -> Int
Pos x + Pos y = Pos (x +^ y)
Neg x + Neg y = Neg (x +^ y)
Pos x + Neg y = x -^ y
Neg x + Pos y = y -^ x
Zero + x = x
x@(Pos _) + Zero = x
x@(Neg _) + Zero = x
--- Subtracts two integers.
(-) :: Int -> Int -> Int
x - Neg y = x + Pos y
x - Pos y = x + Neg y
x - Zero = x
--- Multiplies two integers.
(*) :: Int -> Int -> Int
Pos x * Pos y = Pos (x *^ y)
Pos x * Neg y = Neg (x *^ y)
Neg x * Neg y = Pos (x *^ y)
Neg x * Pos y = Neg (x *^ y)
Zero * _ = Zero
Pos _ * Zero = Zero
Neg _ * Zero = Zero
--- Integer division. The value is the integer quotient of its arguments
--- and always truncated towards zero.
--- Thus, the value of 13 `div` 5
is 2
,
--- and the value of -15 `div` 4
is -3
.
--- Integer remainder. The value is the remainder of the integer division and
--- it obeys the rule x `mod` y = x - y * (x `div` y)
.
--- Thus, the value of 13 `mod` 5
is 3
,
--- and the value of -15 `mod` 4
is -3
.
divmod :: Int -> Int -> (Int,Int)
divmod Zero _ = (Zero,Zero)
divmod (Pos _) Zero = error "division by 0"
divmod (Pos x) (Pos y) = divmodNat x y
divmod (Pos x) (Neg y) = let (d,m) = divmodNat x y in (negate d,m)
divmod (Neg _) Zero = error "division by 0"
divmod (Neg x) (Pos y) = let (d,m) = divmodNat x y in (negate d,negate m)
divmod (Neg x) (Neg y) = let (d,m) = divmodNat x y in (d,negate m)
div,mod :: Int -> Int -> Int
x `div` y = fst (divmod x y)
x `mod` y = snd (divmod x y)
--- Unary minus. Usually written as "- e".
negate :: Int -> Int
negate Zero = Zero
negate (Pos x) = Neg x
negate (Neg x) = Pos x
--- Unary minus on Floats. Usually written as "-e".
negateFloat :: Float -> Float
negateFloat x = prim_negateFloat $# x
prim_negateFloat :: Float -> Float
prim_negateFloat external
-- Constraints
data Success = Success
--- The always satisfiable constraint.
success :: Success
success = Success
--- 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).
(=:=) :: a -> a -> Success
x =:= y | x===y = success
(===) :: a -> a -> Bool
(===) external
--- Concurrent conjunction on constraints.
--- An expression like (c1 & c2) is evaluated by evaluating
--- the constraints c1 and c2 in a concurrent manner.
(&) :: Success -> Success -> Success
(&) external
--- Constrained expression.
--- An expression like (c &> e) is evaluated by first solving
--- constraint c and then evaluating e.
(&>) :: Success -> a -> a
c &> x | c = x
--andBreadth :: [Bool] -> Bool
--andBreadth external
-- Maybe type
data Maybe a = Nothing | Just a
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing = n
maybe _ f (Just x) = f x
-- Either type
data Either a b = Left a | Right b
either :: (a -> c) -> (b -> c) -> Either a b -> c
either f _ (Left x) = f x
either _ g (Right x) = g x
-- Monadic IO
data IO _ -- conceptually: World -> (a,World)
--- Sequential composition of actions.
--- @param a - An action
--- @param fa - A function from a value into an action
--- @return An action that first performs a (yielding result r)
--- and then performs (fa r)
(>>=) :: IO a -> (a -> IO b) -> IO b
(>>=) external
--- The empty action that directly returns its argument.
return :: a -> IO a
return external
--- Sequential composition of actions.
--- @param a1 - An action
--- @param a2 - An action
--- @return An action that first performs a1 and then a2
(>>) :: IO _ -> IO b -> IO b
a >> b = a >>= const b
--- The empty action that returns nothing.
done :: IO ()
done = return ()
--- 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
--- An action that reads a character from standard output and returns it.
getChar :: IO Char
getChar external
--- An action that (lazily) reads a file and returns its contents.
readFile :: String -> IO String
readFile s = prim_readFile $## s
prim_readFile :: String -> IO String
prim_readFile external
--- An action that writes a file.
--- @param filename - The name of the file to be written.
--- @param contents - The contents to be written to the file.
writeFile :: String -> String -> IO ()
writeFile fn s = (prim_writeFile $## fn) $## s
prim_writeFile :: String -> String -> IO ()
prim_writeFile external
--- An action that appends a string to a file.
--- It behaves like writeFile if the file does not exist.
--- @param filename - The name of the file to be written.
--- @param contents - The contents to be appended to the file.
appendFile :: String -> String -> IO ()
appendFile fn s = (prim_appendFile $## fn) $## s
prim_appendFile :: String -> String -> IO ()
prim_appendFile external
--- Catches a possible failure during the execution of an I/O action.
--- (catchFail act err)
:
--- apply action act
and, if it fails,
--- apply action err
catchFail :: IO a -> IO a -> IO a
catchFail external
--- Action to print a string on stdout.
putStr :: String -> IO ()
putStr [] = done
putStr (c:cs) = putChar c >> putStr cs
--- Action to print a string with a newline on stdout.
putStrLn :: String -> IO ()
putStrLn cs = putStr cs >> putChar '\n'
--- Action to read a line from stdin.
getLine :: IO String
getLine = do c <- getChar
if c=='\n' then return []
else do cs <- getLine
return (c:cs)
--- Converts an arbitrary term into an external string representation.
show :: _ -> String
show s = prim_show $## s
prim_show :: _ -> String
prim_show external
--- Converts a term into a string and prints it.
print :: _ -> IO ()
print t = putStrLn (show t)
--- Solves a constraint as an I/O action.
--- Note: the constraint should be always solvable in a deterministic way
doSolve :: Success -> IO ()
doSolve constraint | constraint = done
-- IO monad auxiliary functions:
--- Executes a sequence of I/O actions and collects all results in a list.
sequenceIO :: [IO a] -> IO [a]
sequenceIO [] = return []
sequenceIO (c:cs) = do x <- c
xs <- sequenceIO cs
return (x:xs)
--- Executes a sequence of I/O actions and ignores the results.
sequenceIO_ :: [IO _] -> IO ()
sequenceIO_ = foldr (>>) done
--- Maps an I/O action function on a list of elements.
--- The results of all I/O actions are collected in a list.
mapIO :: (a -> IO b) -> [a] -> IO [b]
mapIO f = sequenceIO . map f
--- Maps an I/O action function on a list of elements.
--- The results of all I/O actions are ignored.
mapIO_ :: (a -> IO _) -> [a] -> IO ()
mapIO_ f = sequenceIO_ . map f
----------------------------------------------------------------
-- Non-determinism:
--- Non-deterministic choice par excellence.
--- The value of x ? y is either x or y.
--- @param x - The right argument.
--- @param y - The left argument.
--- @return either x or y non-deterministically.
(?) :: a -> a -> a
x ? _ = x
_ ? y = y
----------------------------------------------------------------
-- Encapsulated search:
----------------------------------------------------------------
--- Search trees represent the search space of evaluating a given
--- term. For example, the search tree corresponding to
--- the evaluation of
--- (0?1) + (0?1)
--- is Or [Or [Value 0,Value 1],Or [Value 1,Value 2]]
--- whereas the one corresponding to
--- let x=0?1 in x+x
--- is Or [Value 0,Value 2].
data SearchTree a
= Fail
| Value a
| Choice [SearchTree a]
| Suspend
--- Basic search control operator, providing the searchtree lazily with
--- respect to Or branches. The argument of the Value constructor is
--- always evaluated to full normal form. This guarantees that it is
--- really a value and does neither induce another fail nor a
--- branching.
getSearchTree :: a -> IO (SearchTree a)
getSearchTree external
{-
--- Basic operation for generic programming
--- type Data represents arbitrary data types
--- with the strings containing the names of
--- constructors
data Data = Data String [Data]
--- toData residuates on free variables
--- example: toData (Just False) = Data "Just" [Data "False"]
toData :: a -> Data
toData external
--- E.g. fromData (Data unknown "Nothing") = (Data 1 unknown) = Nothing
--- (modulo variable instanciation)
fromData :: Data -> a
fromData external
--- num data might make
data NumData = NumData Int [NumData]
--- toNumData residuates on free variables
toNumData :: a -> NumData
toNumData external
--- toData/fromData are enough for basic generics like
--- show, read, compare and (==).
--- See compare above for a simple example.
--- Other operations can be found in Module Generic
-}
--- depth first search
allValuesD :: SearchTree a -> [a]
allValuesD (Value x) = [x]
allValuesD Fail = []
allValuesD Suspend = []
allValuesD (Choice xs) = concatMap allValuesD xs
--- breadth first search
allValuesB :: SearchTree a -> [a]
allValuesB st = unfoldOrs [st]
where
partition (Value x) y = let (vs,ors) = y in (x:vs,ors)
partition (Choice xs) y = let (vs,ors) = y in (vs,xs++ors)
partition Fail y = y
partition Suspend y = y
unfoldOrs [] = []
unfoldOrs (x:xs) = let (vals,ors) = foldr partition ([],[]) (x:xs) in
vals ++ unfoldOrs ors
--- Inject operator which adds the application of the unary
--- procedure p to the search variable to the search goal
--- taken from Oz. p x comes before g x to enable a test+generate
--- form in a sequential implementation.
inject :: (a->Success) -> (a->Success) -> (a->Success)
inject g p = \x -> p x & g x
--- Identity function used by the partial evaluator
--- to mark expressions to be partially evaluated.
PEVAL :: a -> a
PEVAL x = x
-- Only for internal use:
-- Represenation of higher-order applications in FlatCurry.
apply :: (a->b) -> a -> b
apply external
-- Only for internal use:
-- Representation of conditional rules in FlatCurry.
cond :: Success -> a -> a
cond external
unknown :: a
unknown = let x free in x
-- the end
--- Non-strict equational constraint. Experimental.
(=:<=) :: a -> a -> Success
(=:<=) external