.. Mars Documentation
Copyright (C) 2008 Matt Giuca
11/12/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 .
.. _ref-values:
Values
======
.. sectionauthor:: Matt Giuca
Term-level *values* are units of data which may be stored in variables and
data structures, and passed as arguments. Each value has a corresponding
type, with each :ref:`built-in type ` having a special set
of values, and :ref:`user-defined types ` having a set
of rules that define what values inhabit each type.
This section describes the values that inhabit each type in Mars. It also
describes, for each type family, how the values may be constructed, and how
values are to be displayed (which affects both their appearance when printed
by the interactive prompt, as well as the output of the :func:`show`
function).
.. _ref-value-num:
Numbers
-------
Number values are members of the :type:`Num` type. Mars numbers are
represented internally as binary floating-point numbers; as such, the members
of this type form a subset of the real numbers. The numbers have at least
64-bit "double" precision. The usual caution about floating-point rounding
errors and imprecision applies.
The most common representation is the IEEE 754 binary64 format (commonly known
as "double"), but the implementation is allowed to use any binary
floating-point format that satisfies the following criteria:
* Support for positive and negative values.
* A minimum exponent of at most -1022 and a maximum exponent of at least 1023,
* A mantissa capable of representing integer values up to at least 2^53.
.. note::
The IEEE 754 binary64 format has a 52-bit mantissa. It represents values up
to 2^53 via an implicit 1 bit.
This means that the implementation must provide *at a minimum* a 64-bit
"double" format; any larger binary floating point format is also acceptable,
and programs should be written to allow for variations in floating-point
precision. The implementation is not permitted to represent values as 32-bit
floats (the equivalent of the C :type:`float` type). The above rules mean
that:
* All integers between -2^53 and 2^53, inclusive, are exactly representable.
(-9007199254740992 to 9007199254740992, inclusive.)
* The maximum possible value will be at least 2^1023 (and the same magnitude
on the negative side).
* It is possible to represent at least one non-integer between each pair of
integers in the range -2^52 to 2^52.
* All multiples of 2^-53 between -1 and 1 are exactly representable.
* It will be possible to represent values with a non-zero magnitude at least
as small as 2^-1022. (Note: IEEE binary formats allow for much smaller
numbers to be represented, but this is not required by Mars.)
Unlike in some floating-point systems, there is no distinction between 0 and
-0. The two values are considered equal under all circumstances, and -0 is
displayed without a minus sign.
.. warning::
An overflow (a value with a larger magnitude than the largest representable
value, which is at least 2^1023) will result in undefined behaviour. While
the implementation is likely to generate infinity values, the specifics of
dealing with such values are unspecified and this behaviour should not be
relied upon.
Number values can be created using :ref:`number literal expressions
`. Also, many built-in functions produce number values
(such as all of the arithmetic functions). The string representation of a
number is an ASCII decimal representation, preceded by a hyphen if the value
is negative. Integers (whole numbers) are always displayed without a decimal
point or fractional component. Other numbers are displayed with a decimal
point as a number literal; the implementation is allowed to display numbers
with a large or small magnitude with the "``e``" exponent notation, such as
``4.2e+18`` (which is not a valid number literal).
.. _ref-value-array:
Arrays
------
Array values are members of the :type:`Array` type family.
Arrays in Mars are extensible arrays (sometimes known as "vectors"), the
elements of which may be accessed in constant time. An array is a collection
of elements that has a specific order and allows duplicate elements. Array
types are parameterised by a type variable *a*; this denotes the type of all
of the elements. For example, the type :type:`Array(Num)` permits only
elements of type :type:`Num`.
Array elements are typically referred to by *index*. The index is an integer,
where the first element of the array has index 0, and each subsequent element
has an index 1 greater than the previous. The *length* of the array is the
number of elements contained within it. The index of the last element of the
array is therefore *length*-1. It is not meaningful to talk about elements
with a negative index, or elements whose index is greater than or equal to
*length*.
Individual array elements can be modified in constant time, regardless of the
element's position in the array. Furthermore, new elements can be added to the
end of the array in amortised constant time (typically, this is implemented by
allocating more memory than the array requires, and having the array
occasionally resize by doubling the amount of memory allocated).
.. warning::
Constant-time array updates are currently only possible by importing the
:mod:`impure` library module, and are considered to be an unofficial part
of the language.
:token:`Array literals ` may be used to build array
values. Built-in functions are also available to create and manipulate arrays.
The string representation of an array is the same as the array literal syntax:
a comma-separated list of the string representation of each element, enclosed
in square brackets.
.. _ref-value-function:
Functions
---------
Function values, or *closures*, are members of the :type:`->` and :type:`->io`
type families. As Mars is a functional programming language, all functions
are first-class and may be treated as ordinary values. A function value may be
*called*, with a fixed number of arguments being supplied, and a resulting
value will be *returned*. Some functions may also perform I/O effects (such as
printing) when they are called.
If the :type:`->` type constructor is given *n* arguments, the first *n*-1
arguments are the types of the function parameters, while the final argument
is the type of the function result. For example, values of type ``(a, b) ->
c`` are functions which accept two arguments of types ``a`` and ``b``
respectively, and produce a result of type ``c``.
The data carried by a function value is opaque, but it is likely to include
the code that specified the original function. Because Mars supports
*closures*, function values may also contain other data values. For example,
the expression ``add(1, ...)`` creates a function value that not only includes
the code for the :func:`add` function, but also the value ``1`` which will be
needed when the function is called.
Functions may only be created by being declared at the top level, or through
currying.
The string representation of a function is implementation-defined. Because
functions are considered opaque, it should not technically be obtain any
information about a function other than by calling it. However,
implementations may display information about the function object, such as its
original name or memory location, in order to help identify the function.
The string should therefore not be used in computations (only for debugging or
display purposes).
There are two distinct type constructors for functions: :type:`->` and
:type:`->io`. These distinguish between functions declared as "pure" (without
the :keyword:`io` keyword) and those declared with the :keyword:`io` keyword.
These two types are totally incompatible: it is not possible to convert an I/O
function to a pure function, and a pure function cannot be used in a place
where an I/O function is expected.
.. note::
It is possible to explicitly convert a pure function to an I/O function
using the :func:`toio` functions in the :mod:`iofuncs` module.
.. _ref-value-userdef:
Values of user-defined types
----------------------------
When a type is declared using the :keyword:`type` keyword, a set of values is
created for that type. The values that inhabit each user-defined type are
totally distinct from those of any other type. This is because a) each
user-defined type declares a unique set of data constructor names, and b) each
value of a user-defined type belongs to some constructor of that type.
As described in :ref:`ref-type-declarations`, each user-defined type *T*
consists of a set of one or more data constructors *c0*, ..., *cn*, and each
constructor *ci* has a unique name, and a sequence of zero or more fields
*fi0*, ..., *fim* (where *m* varies from one constructor to another). Each
field *fij* has a type *tij*.
Every value of type *T* belongs to a particular data constructor *ci*, and has
a value of type *tij* for each field of that constructor. User-defined types
may also be parameterised; the type parameter is used to specify the types of
various fields.
For example, the :type:`List` type from the :mod:`prelude` is defined as::
type List(a):
Cons(head :: a, tail :: List(a))
Nil
This type has two data constructors, :func:`Cons` and :func:`Nil`. This means
that every value of type :type:`List(a)` belongs to either the :func:`Cons` or
:func:`Nil` constructor. Values that belong to the :func:`Cons` constructor
contain two sub-values: one value of type *a* and one value of type
:type:`List(a)`. There is only one value that belongs to the :func:`Nil`
constructor: :func:`Nil` (as that constructor has no fields).
Values of a user-defined type can be created by calling the constructor
function of the same name as one of the constructors; this will determine
which constructor the value belongs to and also initialise all of the fields.
Values of parameterless constructor (one declared without parentheses) cannot
be created; they already exist as global values of the same name (for example,
:func:`Nil` is a global constant which is the only value that belongs to the
constructor :func:`Nil`).
The :keyword:`switch` statement can be used to determine which constructor a
particular value belongs to, and also access the value's fields. The
:ref:`assignment statement ` and :ref:`field
reference expression ` can also be used to access
the value's fields. Two values of the same type are considered equal if a)
they both belong to the same constructor, and b) all of their corresponding
field values are equal (see :func:`eq`).
The string representation of a value of a user-defined type is the same as the
construction syntax: for parameterless constructors, it is just the
constructor name. Otherwise, it is the constructor name, followed by a
comma-separated list of the string representation of each field, enclosed in
parentheses.