1 Definitions
define
define-values
define-type
2 Expressions
true
false
quote
#%app
lambda
if
cond
begin
local
and
or
list
values
type-case
try
empty
cons
first
rest
empty?
cons?
map
map2
reverse
not
+
-
*
/
=
>
<
>=
<=
symbol=?
string-append
to-string
string->symbol
symbol->string
equal?
eq?
error
display
box
unbox
set-box!
make-vector
vector-ref
vector-set!
test
test/ exn
3 Types
number
boolean
symbol
string
void
->
listof
boxof
vectorof
4 Type Checking and Inference
Version: 4.2.3

PLAI Typed Language

 #lang plai-typed

The PLAI Typed language is a statically typed language that resembles the PLAI language, though with a much smaller set of syntactic forms and built-in functions.

The PLAI Typed language does not have an entry in DrScheme’s Choose Language dialog. Instead, choose the Module language, and write your program like this:

  #lang plai-typed

  ... all code goes here ....

The default output style of the Module language does not match the PLAI style. To fix it: In the Choose Language dialog, after you select the Module language, click Show Details, and the select Constructor output style.

The body of a plai-typed module is a sequence of definitions and expressions.

1 Definitions

In a define-type declaration, the contract/predicate position for variant fields changes to a colon followed by a type. In addition, define and lambda forms support type annotations on arguments and for results. The syntax is otherwise merely restricted from the normal PLAI language.

(define id expr)
(define id : type expr)
(define (id id/type ...) expr)
(define (id id/type ...) : type expr)
 
id/type = id
  | [id : type]
The definition form with optional type annotations. A type written after (id id/type ...) declares the result type of a function.

(define-values (id/type ...) expr)
 
id/type = id
  | [id : type]
Matches multiple results produced (via values) by expr.

(define-type tyid/abs
  [variant-id (field-id : type)]
  ...)
 
tyid/abs = id
  | (id 'id ...)
Define a type (when tyid/abs is id) or type constructor (when tyid/abs has the form (id 'id ...)) with its variants.

2 Expressions

An expression can be a literal constant that is a number (type number), a string (type string), a symbol (type symbol) written with quote or ', #t (type boolean), or #f (type boolean). An expression also can be a bound identifier (in which acse its type comes from its binding).

(quote symbol)
A symbol.

(#%app expr expr ...)
A function call, which is normally written without the #%app keyword.

(lambda (id/ty ...) expr)
(lambda (id/ty ...) : type expr)
 
id/ty = id
  | [id : type]
A procedure. When a type is written after (id/ty ...), it declares he result type of the function.

(if test-expr expr expr)
(cond [test-expr expr] ...)
(cond [test-expr expr] ... [else expr])
Conditionals. Each test-exprs must have type boolean.

(begin expr ...+)
Sequence.

(local [definition ...] expr)
Local binding.

(and expr ...)
(or expr ...)
Boolean combination. The exprs must have type boolean.

(list elem ...)  (listof 'a)
  elem : 'a
Builds a list. All elems must have the same type.

(values elem ...)  ('a * ...)
  elem : 'a
Types multiple values into one; the type of each elem is independent. Match a values result using define-values.

(type-case tyid/abs val-expr
  [variant-id (field-id ...) expr] ...)
(type-case tyid/abs val-expr
  [variant-id (field-id ...) expr] ...
  [else expr])
 
tyid/abs = id
  | (id 'id ...)
Variant dispatch, where val-expr must have type tyid/abs.

(try expr (lambda () handle-expr))
Either returns expr’s result or catches an exception raised by expr and calls handle-expr.

empty : (listof 'a)
cons : ('a (listof 'a) -> (listof 'a))
first : ((listof 'a) -> 'a)
rest : ((listof 'a) -> (listof 'a))
empty? : ((listof 'a) -> boolean)
cons? : ((listof 'a) -> boolean)
map : (('a -> 'b) (listof 'a) -> (listof 'b))
map2 : (('a 'b -> 'c) (listof 'a) (listof 'b) -> (listof 'c))
reverse : ((listof 'a) -> (listof 'a))
List primitives.

Boolean primitive.

Numeric primitives.

Symbol primitive.

String primitives.

equal? : ('a 'a -> boolean)
eq? : ('a 'a -> boolean)
Comparison primitives.

error : (symbol string -> 'a)
Error primitive

display : ('a -> void)
Output primitive

box : ('a -> (boxof 'a))
unbox : ((boxof 'a) -> 'a)
set-box! : ((boxof 'a) 'a -> void)
Box primitives.

make-vector : (number 'a -> (vectorof 'a))
vector-ref : ((vectorof 'a) number -> 'a)
vector-set! : ((vectorof 'a) number 'a -> void)
Vector primitives.

test : ('a 'a -> void)
test/exn : ((-> 'a) string -> void)
Test primitive forms that do not actually produce a void value. Instead, they produce results suitable for automatic display through a top-level expression. The void type merely prevents your program from using the result.

3 Types

Primitive types.

(type ... -> type)
Type for a function.

(type * ...+)
Types for tuples.

()
Type for the empty tuple.

(listof type)
Type for a list of elements.
(boxof type)
Type for a mutable box.
(vectorof type)
Type for a vector of elements.

4 Type Checking and Inference

Type checking and inference is just as in ML (Hindley-Milner), with a few small exceptions:

When typechecking fails, the error messages reports and highlights (in pink) all of the expressions whose type contributed to the failure. That’s often too much information. As usual, explicit type annotations can help focus the error message.