This is an old revision of the document!
Types and parameters
Alvis uses the Haskell's type system. Types in Haskell are strong, static and can be automatically inferred. The strong property means that the type system guarantees that a program cannot contain errors coming from using improper data types, such as using a string as an integer. Moreover, Haskell does not automatically coerce values from one type to another. The static property means that the compiler knows the type of every value and expression at compile time, before any code is executed. Haskell's combination of strong and static typing makes it impossible for type errors to occur at runtime.
Basic data types
Selected basic Haskell types recommended to be used in Alvis are as follows:
- Char – Unicode characters.
- Bool – Values in Boolean logic (True and False).
- Int – Fixed-width integer values – The exact range of values represented as Int depends on the system's longest native integer.
- Double – Float-point numbers typically 64 bits wide and uses the system's native floating-point representation.
Composite data types
The most common composite data types in Haskell (and Alvis) are lists and tuples.
- Lists – A list is a sequence of elements of the same type, with the elements being enclosed in square brackets and separated by commas.
- Tuples – A tuple is a sequence of elements of possibly different types, with the elements being enclosed in parentheses and separated by commas. Tuples containing different number of types of elements have disting types, as do tuple whose types appear in different orders.
Remark: Haskell represents a text string as a list of Char values, but the name String can be used.
[1,2,3,4] -- type [Int] ['a','b','c'] -- type [Char] (String) [True,False] -- type [Bool] (1,2) -- type (Int,Int) ('a',True) -- type (Char,Bool) ("abc",1,True) -- type (String,Int,Bool)
Listing 1. Examples of Haskell composite data types
Type aliases and new data types
To make the source code more readable, one can introduce a synonym for an existing type as shown in Listing 2.
type AgentID = Int type InputData = (Int,Int) -- pair type TrafficSignal = [Char] -- list
Listing 2. Synonyms for data types
data AgentDescription = AgentDesc Int String [String]; myAgent = AgentDesc 1 "Buffer" ["put","get"];
Listing 3. New composite data type
A new data type is defined using the data keyword (see Listing 3). The identifier after the data keyword is the name of the new type, while the identifier after the = sign is called value constructor (data constructor). A value constructor is a special function, which name, as the name of type, must start with an uppercase letter. Types placed after a value constructor name are called components of the type. A value constructor is used to create a new value of the corresponding type as shown in the second line of Listing 3. A value constructor name can be the same as the type one.
We can used more than one value constructor for one type. Such types in Haskell are called algebraic data types. Each value constructor is separated in the definition by the | sign. Each of an algebraic data type's value constructor can take zero or more arguments. An algebraic data type can be used to define an enumeration type or a type with different variants of data (see Listing 4).
data Move = East | South | West | North; type Point = (Double,Double); data Shape = Circle Point Double | Rectangle Point Point;
Listing 4. Examples of Haskell algebraic data types
Remark:
Haskell requires type names to start with an upper-case letter, and variable and function names to start with a lower-case letter. Exception to the rule are so-called constructor functions that must always start with a upper-case letter. In the examples from listings 3 and 4 AgentDesc
, East
, South
etc. are constructor functions.
Constants
Constants are defined using parameterless Haskell functions as shown in Listing 5.
size = 10; name = "Agent";
Listing 5. Examples of constants
The = symbol in Haskell code represents meaning – the name on the left is defined to be the expression on the right. This meaning of = is valid in the preamble. In the implementation part, the = symbol stands for the assignment operator.
Agents' parameters
Parameters are defined using the Haskell syntax. Each parameter is placed in a separate line. The line starts with a parameter name, then the :: symbol is placed followed by the parameter type. The type must be followed by the = symbol and the parameter initial value as shown in Listings 6 and 7.
size :: Int = 7; queue :: [Double] = []; inputData :: (Int, Char) = (0, 'x');
Listing 6. Examples of parameters definitions
agent Buffer { v :: Int = 0; -- ... }
Listing 7. Part of Buffer agent implementation with a parameter definition