Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
Curry: An Integrated Functional Logic Language
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
and introduces a new n-ary type constructor T and k new (data) constructors C1, . . . , Ck, where<br />
each Ci has the type<br />
τi1 -> · · · -> τini -> T α1 . . . αn<br />
(i = 1, . . . , k). Each τij is a type expression built from the type variables α1, . . . , αn and some<br />
type constructors. <strong>Curry</strong> has a number of built-in type constructors, like Bool, Int, -> (function<br />
space), or, lists and tuples, which are described in Section 4.1. Since <strong>Curry</strong> is a higher-order<br />
language, the types of functions (i.e., constructors or operations) are written in their curried form<br />
τ1 -> τ2 -> · · · -> τn -> τ where τ is not a functional type. In this case, n is called the arity of<br />
the function. For instance, the datatype declarations<br />
data Bool = True | False<br />
data List a = [] | a : List a<br />
data Tree a = Leaf a | Node (Tree a) a (Tree a)<br />
introduces the datatype Bool with the 0-ary constructors (constants) True and False, and the<br />
polymorphic types List a and Tree a of lists and binary trees. Here, “:” is an infix operator, i.e.,<br />
“a:List a” is another notation for “(:) a (List a)”. Lists are predefined in <strong>Curry</strong>, where the<br />
notation “[a]” is used to denote list types (instead of “List a”). The usual convenient notations<br />
for lists are supported, i.e., [0,1,2] is an abbreviation for 0:(1:(2:[])) (see also Section 4.1).<br />
A data term is a variable x or a constructor application c t1 . . . tn where c is an n-ary constructor<br />
and t1, . . . , tn are data terms. <strong>An</strong> expression is a variable or a (partial) application ϕ e1 . . . em<br />
where ϕ is a function or constructor and e1, . . . , em are expressions. A data term or expression is<br />
called ground if it does not contain any variable. Ground data terms correspond to values in the<br />
intended domain, and expressions containing operations should be evaluated to data terms. Note<br />
that traditional functional languages compute on ground expressions, whereas logic languages also<br />
allow non-ground expressions.<br />
2.2 Type Synonym Declarations<br />
To make type definitions more readable, it is possible to specify new names for type expressions by<br />
a type synonym declaration. Such a declaration has the general form<br />
type T α1 ... αn = τ<br />
which introduces a new n-ary type constructor T . α1, . . . , αn are pairwise distinct type variables<br />
and τ is a type expressions built from type constructors and the type variables α1, . . . , αn. The type<br />
(T τ1 . . . τn) is equivalent to the type {α1 ↦→ τ1, . . . , αn ↦→ τn}(τ), i.e., the type expression τ where<br />
each αi is replaced by τi. Thus, a type synonym and its definition are always interchangeable and<br />
have no influence on the typing of a program. For example, we can provide an alternative notation<br />
for list types and strings by the following type synonym declarations:<br />
type List a = [a]<br />
type Name = [Char]<br />
Since a type synonym introduces just another name for a type expression, recursive or mutually<br />
dependent type synonym declarations are not allowed. Therefore, the following declarations are<br />
invalid:<br />
4