.. Mars Documentation
Copyright (C) 2008 Matt Giuca
3/9/2008
.. This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.. This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.. You should have received a copy of the GNU General Public License
along with this program. If not, see .
:mod:`prelude` --- Common functions
===================================
.. sectionauthor:: Matt Giuca
.. moduleauthor:: Matt Giuca
.. module:: prelude
:synopsis: Common standard library functions.
The prelude is where the most common functions are found. This module is
typically imported by any *Mars* module.
It is not imported by default, but if :command:`mars` is run without any
command-line arguments, this module will be loaded.
Higher-order helper functions
-----------------------------
.. function:: id(x :: a) :: a = x
The identity function; returns *x*.
.. function:: const(k :: a) :: b -> a
Returns a function which returns *k*, regardless of its argument.
.. function:: apply0(f :: () -> r) :: r = f()
Calls *f* with no arguments.
.. function:: apply1(f :: a -> r, x :: a) :: r = f(x)
Calls *f* with *x* as an argument.
.. function:: apply2(f :: (a, b) -> r, x :: a, y :: b) :: r = f(x, y)
Calls *f* with *x* and *y* as arguments.
.. function:: curry2(f :: (a, b) -> r) :: a -> b -> r
Converts *f* into a curried function -- the resulting function takes one
argument and returns a function that takes the second argument and calls
*f* with both.
.. function:: curry3(f :: (a, b, c) -> r) :: a -> b -> c -> r
Converts *f* into a curried function -- the resulting function takes one
argument and returns a function that takes the second argument and so on,
and calls *f* with all of the arguments.
.. function:: curry4(f :: (a, b, c, d) -> r) :: a -> b -> c -> d -> r
Converts *f* into a curried function -- the resulting function takes one
argument and returns a function that takes the second argument and so on,
and calls *f* with all of the arguments.
.. function:: compose(f :: b -> c, g :: a -> b) :: a -> c
Creates a function which takes one argument and passes it to *g*, then
passes the result of that to *f*.
.. function:: flip(f :: (a, b) -> c) :: (b, a) -> c
Creates a function which passes its two arguments to *f* in the reverse
order.
Logic functions
---------------
.. constant:: false :: Num = 0
The number 0, representing false.
.. constant:: true :: Num = 1
The number 1, representing true.
.. function:: and(x :: Num, y :: Num) :: Num
The Boolean AND of *x* and *y*. If *x* is nonzero, returns *y*; otherwise,
returns 0.
.. function:: or(x :: Num, y :: Num) :: Num
The Boolean OR of *x* and *y*. If *x* is zero, returns *y*; otherwise,
returns *x*.
.. function:: not(x :: Num) :: Num
The Boolean NOT of *x*. If *x* is zero, returns 1; otherwise, returns 0.
Comparison functions
--------------------
.. function:: ne(x :: a, y :: a) :: Num
1 if *x* is not equal to *y* (according to :func:`eq`), 0 otherwise.
.. function:: lt(x :: Num, y :: Num) :: Num
1 if *x* is less than *y*, 0 otherwise.
.. function:: le(x :: Num, y :: Num) :: Num
1 if *x* is less than or equal to *y*, 0 otherwise.
.. function:: gt(x :: Num, y :: Num) :: Num
1 if *x* is greater than *y*, 0 otherwise.
.. function:: ge(x :: Num, y :: Num) :: Num
1 if *x* is greater than or equal to *y*, 0 otherwise.
Arithmetic
----------
.. function:: neg(x :: Num) :: Num
Returns the negation of *x* (0 - *x*).
.. function:: abs(x :: Num) :: Num
Returns the absolute value of *x* (a positive number with the same
magnitude).
.. function:: min(x :: Num, y :: Num) :: Num
The lesser value of *x* and *y*.
.. function:: max(x :: Num, y :: Num) :: Num
The greater value of *x* and *y*.
.. function:: ceil(x :: Num) :: Num
Returns the smallest integer that is greater than or equal to *x*. This
rounds *x* towards positive infinity.
.. function:: trunc(x :: Num) :: Num
Rounds *x* to an integer, towards zero.
.. function:: round(x :: Num) :: Num
Rounds *x* towards the nearest integer. Halfway values (those that end in
".5") are rounded away from zero.
Tuple types and operations
--------------------------
.. note::
Mars doesn't have a general tuple type. It just defines specific
types for tuples of arity two, three and four.
.. type:: Pair(a, b)
::
Pair(a, b)
A pair of any two values.
.. function:: fst(pair :: Pair(a, b)) :: a
The first value of a given *pair*.
.. function:: snd(pair :: Pair(a, b)) :: b
The second value of a given *pair*.
.. type:: Triple(a, b, c)
::
Triple(a, b, c)
A sequence of any three values.
.. type:: Quadruple(a, b, c, d)
::
Quadruple(a, b, c, d)
A sequence of any four values.
Linked List type and operations
-------------------------------
.. type:: List(a)
::
Cons(head :: a, tail :: List(a))
Nil
A linked list of values, all of the same type. This type is incompatible
with the :type:`Array` type, but it is possible to convert between the
two using :func:`list_to_array` and :func:`array_to_list`.
.. function:: empty(list :: List(a)) :: Num
Test if *list* is empty. 1 if it is empty, 0 otherwise.
.. function:: head(list :: List(a)) :: a
The first item in *list*. Aborts if *list* is empty.
.. function:: tail(list :: List(a)) :: List(a)
The list corresponding to all but first item in *list*. Aborts if *list*
is empty.
.. function:: ref(list :: List(a), index :: Num) :: a
The element of *list* with index *index*. The first element has index 0.
It is an error if *index* is non-integral, equal to or greater than the
length of the list, or negative.
.. function:: length(list :: List(a)) :: Num
The number of elements in *list*.
.. function:: map(function :: a -> b, list :: List(a)) :: List(b)
Applies *function* to each item in *list*, producing a new list containing
each of the results.
For example, ``map(f, array_to_list([a, b, c]))`` computes
``array_to_list([f(a), f(b), f(c)])``.
.. function:: filter(predicate :: a -> Num, list :: List(a)) :: List(a)
Produces a new list containing only the items in *list* for which
*function* returns a nonzero result.
.. function:: foldl(function :: (a, b) -> a, initial :: a, list :: List(b)) :: a
Applies *function* to *initial* and the head of *list*, then to the result
of that and the second element of *list*, and so on, returning the result
of the final application.
For example, ``foldl(f, z, array_to_list([a, b, c]))`` computes
``f(f(f(z, a), b), c)``.
.. function:: foldl1(function :: (a, a) -> a, list :: List(a)) :: a
:func:`foldl` without an initial value.
Applies *function* to the first and second elements of *list*, then to the
result of that and the third element of *list*, and so on, returning the
result of the final application.
For example, ``foldl1(f, array_to_list([a, b, c, d]))`` computes
``f(f(f(a, b), c), d)``.
.. function:: foldr(function :: (a, b) -> b, initial :: b, list :: List(a)) :: b
Applies *function* to the last element of *list* and *initial*, then to the
second-last element of *list* and the result of that, and so on, returning
the result of the final application.
For example ``foldr(f, z, array_to_list([a, b, c]))`` computes
``f(a, f(b, f(c, z)))``.
.. function:: foldr1(f :: (a, a) -> a, l :: List(a)) :: a
:func:`foldr` without an initial value.
Applies *function* to the second-last and last elements of *list*, then to
the third-last element and the result of that, and so on, returning the
result of the final application.
For example, ``foldr1(f, array_to_list([a, b, c, d]))`` computes
``f(a, f(b, f(c, d)))``.
.. function:: sum(list :: List(Num)) :: Num
Computes the sum of all numbers in *list*.
.. function:: minimum(list :: List(Num)) :: Num
Computes the minimum of all numbers in *list*.
.. function:: maximum(list :: List(Num)) :: Num
Computes the minimum of all numbers in *list*.
.. function:: reverse(list :: List(a)) :: List(a)
Returns the elements of *list* in reverse order.
.. function:: append(list1 :: List(a), list2 :: List(a)) :: List(a)
Returns the elements of *list1* concatenated onto the front of *list2*.
Note that this operation is linear in the length of *list1*, but constant
in the length of *list2* (it makes a copy of *list1* but not *list2*).
.. function:: index(list :: List(a), item :: a) :: Num
Returns the index of the first element of *list* which compares equal
(according to :func:`eq`) to *item*, or -1 if no element compares equal.
The first element has index 0.
.. function:: elem(item :: a, list :: List(a)) :: Num
Returns 1 if any element of *list* compares equal (according to :func:`eq`)
to *item*; 0 otherwise.
.. function:: zip(list1 :: List(a), list2 :: List(b)) :: List(Pair(a, b))
Combine pairwise elements of *list1* and *list2* into a single list of
pairs. For example, ``zip(array_to_list([a, b, c]), array_to_list([x, y,
z]))`` produces ``array_to_list([Pair(a, x), Pair(b, y), Pair(c, z)])``.
If the two lists are not the same length, the resulting list is as long as
the shorter list, with the remaining elements of the longer list discarded.
.. function:: unzip(list :: List(Pair(a, b))) :: Pair(List(a), List(b))
Separate a list of pairs into a pair of lists with corresponding elements
of *list*. The first output list contains the :func:`fst` of each element
of *list*, and the second output list contains the :func:`snd` of each
element. For example, ``unzip(array_to_list([Pair(a, x), Pair(b, y),
Pair(c, z)]))`` produces ``Pair(array_to_list([a, b, c]), array_to_list([x,
y, z]))``.
.. function:: range(start :: Num, end :: Num) :: List(Num)
Returns a list of integers from *start*, inclusive, to *end*, exclusive.
The arguments should be integers (if not, this will return values spaced 1
apart between *start* and *end*).
.. function:: list_to_array(list :: List(a)) :: Array(a)
Convert *list* to an :type:`Array` of the same elements.
.. function:: array_to_list(array :: Array(a)) :: List(a)
Convert *array* to a :type:`List` of the same elements.
Array operations
----------------
.. function:: array_map(function :: a -> b, array :: Array(a)) :: Array(b)
Applies *function* to each item in *array*, producing a new array
containing each of the results.
For example, ``array_map(f, [a, b, c])`` computes ``[f(a), f(b), f(c)]``.
.. function:: array_filter(function :: a -> Num, array :: Array(a)) :: Array(a)
Produces a new array containing only the items in *array* for which
*function* returns a nonzero result.
.. function:: array_foldl(function :: (a, b) -> a, initial :: a, array :: Array(b)) :: a
Applies *function* to *initial* and the first element of *array*, then to
the result of that and the second element of *array*, and so on, returning
the result of the final application.
For example, ``array_foldl(f, z, [a, b, c])`` computes ``f(f(f(z, a), b),
c)``.
.. function:: array_foldl1(function :: (a, a) -> a, array :: Array(a)) :: a
:func:`array_foldl` without an initial value.
Applies *function* to the first and second elements of *array*, then to the
result of that and the third element of *array*, and so on, returning the
result of the final application.
For example, ``array_foldl1(f, [a, b, c, d])`` computes ``f(f(f(a, b), c),
d)``.
.. function:: array_foldr(function :: (a, b) -> b, initial :: b, array :: Array(a)) :: b
Applies *function* to the last element of *array* and *initial*, then to
the second-last element of *array* and the result of that, and so on,
returning the result of the final application.
For example ``array_foldr(f, z, [a, b, c])`` computes ``f(a, f(b, f(c,
z)))``.
.. function:: array_foldr1(function :: (a, a) -> a, array :: Array(a)) :: a
:func:`array_foldr` without an initial value.
Applies *function* to the second-last and last elements of *array*, then to
the third-last element and the result of that, and so on, returning the
result of the final application.
For example, ``array_foldr1(f, [a, b, c, d])`` computes ``f(a, f(b, f(c,
d)))``.
.. function:: array_substr(array :: Array(a), start :: Num, length :: Num) :: Array(a)
Returns an array consisting of all elements of *array* from *start*,
inclusive, to *start* + *length*, exclusive. Out-of-range indices are
dropped silently, so the resulting array may be shorter than *length*.
It is an error if *start* is non-integral. If *length* is non-integral, it
is rounded up.
.. function:: array_index(array :: Array(a), item :: a) :: Num
Returns the index of the first element of *array* which compares equal to
*item*, or -1 if no element compares equal. The first element has index 0.
.. function:: array_elem(item :: a, array :: Array(a)) :: Num
Returns 1 if *item* is an element of *array*; 0 otherwise.
.. function:: array_zip(array1 :: Array(a), array2 :: Array(b)) :: Array(Pair(a, b))
Combine pairwise elements of *array1* and *array2* into a single array of
pairs. For example, ``zip([a, b, c], [x, y, z])`` produces ``[Pair(a, x),
Pair(b, y), Pair(c, z)]``.
If the two arrays are not the same length, the resulting array is as long
as the shorter array, with the remaining elements of the longer array
discarded.
.. function:: array_unzip(array :: Array(Pair(a, b))) :: Pair(Array(a), Array(b))
Separate an array of pairs into a pair of arrays with corresponding
elements of *array*. The first output array contains the :func:`fst` of
each element of *array*, and the second output array contains the
:func:`snd` of each element. For example, ``unzip([Pair(a, x), Pair(b, y),
Pair(c, z)])`` produces ``Pair([a, b, c], [x, y, z])``.
.. function:: array_range(start :: Num, end :: Num) :: Array(Num)
Returns an array of integers from *start*, inclusive, to *end*, exclusive.
(See :func:`range` for a discussion on non-integral inputs to this
function.)
Maybe type and operations
-------------------------
.. type:: Maybe(a)
::
Just(value :: a)
Nothing
A container for a single value, which may or may not exist. As *Mars* has
no "``null``" value, any value which might be non-existant should have type
:type:`Maybe(a)`, and non-existant values should be represented as
:func:`Nothing`.
.. function:: null(value :: Maybe(a)) :: Num
Test if *value* is empty. 1 if it is :func:`Nothing`, 0 if it is a
:func:`Just` value.
I/O
---
.. constant:: eof :: Num = -1
Represents the "end of file" condition in the output of the built-in
function :func:`get_char`. Note that :const:`eof` is not actually a
character; it is a special value indicating that no more bytes can be read
from a file.
.. function:: print_char_list(string :: List(Num)) :: io Num
Writes *string* to standard output, where *string* is a list of byte
values. This calls :func:`put_char` on each element of *string*. It is an
error if any element is non-integral or outside the range [0, 255]. Does
not print a newline. See also: :func:`print_string`.
.. function:: print_string(string :: Array(Num)) :: io Num
Writes *string* to standard output. This calls :func:`put_char` on each
element of *string*. It is an error if any element non-integral or is
outside the range [0, 255]. Does not print a newline.
.. note::
This function (as with all input/output functions) can only be called
from an :keyword:`io` context. To print text from a technically-pure
function, consider the :func:`trace` function in the :mod:`debug`
module. Note that this is only intended for debugging purposes!
.. function:: print_value(value :: a) :: io Num
Writes a string representation of *value* to standard output. This is
equivalent to ``print_string(show(value))``. See also:
:func:`print_string`, :func:`show`.
.. function:: get_line_list() :: io List(Num)
Reads a line (sequence of bytes terminated by ``'\n'``) from standard
input, returning a list of byte values. The list does not contain the
``'\n'`` character. See also: :func:`get_line`.
.. function:: get_line() :: io Array(Num)
Reads a line (sequence of bytes terminated by ``'\n'``) from standard
input, returning a string. The string does not contain the ``'\n'``
character.