GIML: A Glossary

! dereference
'a type parameter
''a ditto with equality
# record reference
# truncated strings
... truncated lists
: .. of type
:: cons
=> anonymous functions
@ append
_ anonymous parameter
and mutual recursion
as another name for..
andalso boolean and
datatype data definition
@ anonymous functions
fun function definition
hd head of a list
if .. then .. else ..
it last result
length length of a list
null test for empty list
o function composition
op infix to prefix
orelse boolean operator
rev reverse a list
size length of a string
substring extract part of a string
tl tail of a list
type name a type
val define a label
Never use this - it dereferences pointers. Its use brings shame on all who dabble with it (and an F grade if it shows up in assessments).
- val nasty = ref 1;
val nasty = ref 1 : int ref
- !nasty;
val it = 1 : int
- nasty := 2;
val it = () : unit
- !nasty;
val it = 2 : int
A "type variable" used to indicate that any type can be used here (also 'b 'c ...)
- length;
val it = fn : 'a list -> int
The input type for length is 'a because length works for lists of any type (e.g. lists of integers or strings or functions)
- datatype 'a Leafless = lltip | llnode of 'a * 'a Leafless * 'a Leafless;

- datatype ('a,'b) Tree = tip of 'a
                        | node of 'b*(('a,'b)Tree)*(('a,'b)Tree);
Leafless is a tree with data at the nodes only. Tree is a tree with 'a s at the tips and 'b s at the nodes.
Used to indicate a type which supports equality. Ordinary types like int and string support equality (you can test to see if one int equals another). Some types (such as functions) do not permit such tests.
- fun member x nil = false
= |   member x (h::t) = (x=h) orelse member x t;
val member = fn : ''a -> ''a list -> bool
We can apply member only where the type permits equality...
- member 1 [2,3];
val it = false : bool
The above is OK as int supports equality
- member tl [tl,rev];
std_in:11.1-11.18 Error: operator and operand don't agree (equality type required)
  operator domain: ''Z
  operand:         'Y list -> 'Y list
  in expression:
    member tl
The above fails type checking as tl and rev are functions, lists of functions may be used where the type is simple 'a...
- length [tl,rev];
val it = 2 : int
This is used to access fields of a record (not covered in GIML)
- val emp1 = {name="Andrew",address="Cloud-cuckooland",salary=1000000};
- #salary emp1;
val it = 1000000 : int
Tuples are "special" records with field named 1, 2, 3 ...
val it = 7 : int
Long strings are not printed in full in some versions of ML. After 70 or so characters the # appears.
- let fun s x = x^ x in  s(s(s(s(s("on and "))))) end;
val it =
  "on and on and on and on and on and on and on and on and on and on and #"
  : string
The default value may be changed with the following line..
System.Print.stringDepth := 10000; 
Long lists are not printed in full in some versions of ML. After 12 or so items the characters ... appear.
- let fun s x = x @ x in s(s(s(s([1])))) end;
val it = [1,1,1,1,1,1,1,1,1,1,1,1,...] : int list
The default value may be changed with the following line...
 System.Print.printLength := 1000;
May be used to specify type.
- fun add(x : int, y: int) = x + y;
val add = fn : int * int -> int
Cons. This constructs a list - it takes an item and a list and returns a list.
- 1::[2,3];
val it = [1,2,3] : int list

- 1::2::3::nil;
val it = [1,2,3] : int list

The append operator. This is used to join two lists together.
Example of use:
- [1,2,3] @ [3,4,5];
val it = [1,2,3,3,4,5] : int list
The definition of @ is as follows...
fun    nil @ x = x
|   (h::t) @ x = h::(t@x);
The underscore can be used as a "place-holder" in patterns on the left hand side of equations - it should never appear on the right. It may be used to indicate the presence of a parameter whose value is not used. This "anonymous" label may be repeated on the left hand side - in which case it may stand for different values in each position.
For example in the definition of hd we match the pattern h::t but we do not care about the value of t
fun hd(h::_)=h;
instead of
fun hd(h::t)=h;
This may be used to define mutually recursive functions and datatypes.
datatype Expr       = Sum of Term list
and      Term       = Product of Factor list
and      Factor     = Variable of string | Value of int | Bracket of Expr;
(* Not a good example as it is easier to have just one type here ...
datatype Expr = Sum of Expr list | 
                Prod of Expr list |
                Var of string|
                Val of int;
fun foo(h::t) = h+bar t
|   foo nil   = 0
and bar(h::t) = (~h)+foo t
|   bar nil   = 0;
A boolean "and". Note that it is lazy in that the second value is not evaluated unless it is required. (also see orelse)
- (42 div 7 = 6) andalso (42 mod 7 = 0);
val it = true : bool
- (42 div 7 = 7) andalso (hd nil = 0);
val it = false : bool
Note that no run time error occurs even though hd nil would raise an exception.
This can be used to allow more than one way of referring to a structure. This is a perfectly safe and sensible thing to do given referential transparency.
fun triangle nil = nil
|   triangle (l as h::t) = l::triangle t;

triangle ["Oh", "Sir", "Jasper"];
val it = [["Oh","Sir","Jasper"],["Sir","Jasper"],["Jasper"]] : string list list
Used to introduce new datatypes. Alternate "tags" or constructors are given components using the of key word.
- datatype Shape = Square of int | Rectangle of int * int;
datatype  Shape
  con Rectangle : int * int -> Shape
  con Square : int -> Shape
fn ... => ...
Allows functions to be defined without being named (anonymous functions). Example:
(fn x => 2*x)
This key word is used to define a function.
Returns the head of the list - that is the first element of a list.
- hd ["one", "two", "three"];
val it = "one" : string
The functions hd and tl are very basic functions, they do not show up in ML programs so often as they might because pattern matching often makes their use unnecessary. A typical recursive function in ML might be defined as follows using pattern matching:
fun sum nil   = 0
|   sum(h::t) = h + sum t;
Without pattern matching we would use hd, tl and null.
fun sum x = if null x then 0 else (hd x) + sum(tl x);
The if B then X else Y structure returns a value, in the same way that the (B) ? X : Y structure does in c.
In this example count x l returns the number of times that value x occurs in list l.
fun count x nil = 0
|   count x (h::t) = if x=h then 1+count x t else count x t;
or even
fun count x nil = 0
|   count x (h::t) = (if x=h then 1 else 0) + count x t;
This "variable" holds the result of the last calculation. It can be handy to use when investigating - but it has no place in a "finished" program.
Returns the number of items in a list:
length [2,3,4];
val it = 3 : int
The definition of length is as follows
fun length nil   = 0
|   length(h::t) = 1 + length t;
Returns true if the input is an empty list; false otherwise.
- null ["one", "two", "three"];
val it = false : bool
Composes two functions. The result is a function. For example
- (implode o rev o explode) "Bolton";
val it = "notloB" : string
A handy thing to turn infix operators into prefix functions
- (op +)(2,3);
val it = 5 : int
- fold (op @) [[1,2],[3,4]] nil;
val it = [1,2,3,4] : int list
Same kind of thing as andalso
Reverses a list
- rev ["Andrew", "was", "here"];
val it = ["here","was","Andrew"] : string list
returns the size of a string
- size "five";
val it = 4 : int
The call substring(s, i, n) returns n character from string s at position i. The first character is at position 0.
- substring("delicatessen",4,3);
val it = "cat" : string
Returns the tail of a list: that is everything except the first element
- tl ["one", "two", "three"];
val it = ["two","three"] : string list
Raises the exception Tl if the input list is empty.
Allows an alias for a type
type employee = string * string * int;
Used to make bindings
- val pi = 3.14159;