Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.1 6/24/83; site cstvax.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!seismo!mcvax!ukc!cstvax!bob
From: bob@cstvax.UUCP (Bob Harper)
Newsgroups: net.lang
Subject: Re: Type-System Questions
Message-ID: <8@cstvax.UUCP>
Date: Tue, 29-Oct-85 06:34:20 EST
Article-I.D.: cstvax.8
Posted: Tue Oct 29 06:34:20 1985
Date-Received: Sat, 2-Nov-85 04:47:30 EST
References: <15100005@ada-uts.UUCP>
Reply-To: bob@cstvax.UUCP (Bob Harper)
Followup-To: net.lang
Organization: Comp. Sc., Edinburgh Univ., Scotland
Lines: 147

In article <15100005@ada-uts.UUCP> richw@ada-uts.UUCP writes:
>
>Does anyone know of any languages that either:
>
>1) Attempts to do compile-time type-checking via "type inference"?
>   That is, by analyzing the data flow of a program, the compiler
>   tells you when it's sure that a type mismatch occurs -- this allows
>   the programmer to not explicitly declare types.  Yes, I know that
>   this can lead to situations where a variable may refer to objects
>   of several types, and is thus not perfect.  I'm still curious to
>   know if systems exist which try this.
>
The programming language ML developed here at Edinburgh C.S. does just that.
The use of type inference in programming was pioneered by Robin Milner in
the design of ML (references below).  ML is a strongly--typed, polymorphic
functional programming language that was originally designed as the meta--
language (hence the name) for LCF, a logic for reasoning about programs.
It has recently been revamped and standardized, and is now known as Standard ML.
The language can be separated into two major components: the core
language and the module facility.  The core language implementation is complete
and available; the module facility implementation is in progress.

Enough advertising.  The type system of ML has the property that no well--typed
program can incur a type error at run time (where a type error includes things
like trying to add a string to a boolean), and furthermore every program has a
unique most--general type that can be automatically inferred without any type
declarations by the user.  The phrase ``most--general'' can be made mathemat--
ically precise, but, roughly speaking, it means that the ML compiler assigns
the broadest meaningful type that it can.  An example will help.  Consider the
function defined as follows:

	fun id(x) = x;

This function takes a value x as argument and returns x as result.  What type
should id have?  It clearly does not care whether the argument is an integer
or a boolean or a function or a list or whatever --- the functional behavior
is the same in all cases.  Therefore the type assigned to id is not, say,
int->int or bool->bool or ... but rather 'a->'a, where 'a (pronounced ``alpha'')
is a type variable ranging over types.  For id to have the type 'a->'a means
that it can be applied to an argument of type 'a (for any type at all), and
it returns a value of type 'a (the same 'a).  This means that we can apply id
to several arguments of vastly different types.  All of the following uses are
legal, and their type is given:

	id(3)			int
	id(true)		bool
	id(id)			('a->'a)->('a->'a) [!]

The combined fact of inferring a most--general type together with the ability
to use functions at several distinct types (all instances of the most general
type) is called polymorphism.  The function id is polymorphic (literally, many
shapes) because it can take and returns values of many different types.  (The
term was coined by Strachey; he distinguished two forms: parametric and ad--hoc
polymorphism; the former is what ML gives, the latter is now called ``overloading'',
whereby the same identifier is used to refer to *different* functions, whereas
here the identifier id refers to exactly *one* function: the compiler does *not*
build different versions of id, one for each type used.  Thus ML provides a much
more elegant way of achieving polymorphism than does, say, ADA, which simply
macro expands each use for each type argument.)

By the way, there is no problem about a variable referring to objects of
several different types.  SML accounts for polymorphic assignment in more
or less the same way as outlined above for functions, and thus preserves
strong typing without sacrificing type inference or compile--time typechecking.

Here are some salient points about SML:

	1. Functions are first--class objects (that is what we mean by saying
	   that SML is a functional language).

	2. SML is statically (lexically) scoped.  (I'll be happy to take on any
	   dynamic scoping fans if they'd like.)

	3. SML has imperative constructs (assignment, iteration), but also
	   has a purely functional subset.

	4. SML has an extensible type system, including simple type abbreviation,
	   definition of new structural types (like trees or whatever), and
	   definition of abstract types (stacks and the like).

	5. SML is polymorphic and provides complete compile--time type inference.

	6. SML has a module facility to support the structuring of large programs
	   and to provide facilities for separate compilation and linking.

This is getting long--winded, so I'll end with a reference list:

1. Robin Milner, ``A theory of type polymorphism in programming'', JCSS 17(3),
December, 1978.

2. Michael Gordon, Robin Milner, and Christopher Wadsworth, ``Edinburgh LCF'',
Springer Verlag LNCS 78 (1979).

3. Luis Damas and Robin Milner, ``Principal type schemes for functional
programs'', Proc. 9th POPL, 1982.

4. Robert Harper, David MacQueen, and Robin Milner, ``The definition of
Standard ML'' (to appear as Edinburgh CS Technical Report).

5. David MacQueen, ``Modules for Standard ML'', Bell Labs, October, 1985.
(see also POPL in January 86).

6. Luca Cardelli, ``Amber'', Bell Labs, 1985.  (a descendant of ML).

>or...
>
>2) Includes BOTH compile-time types and run-time, "manifest" types?
>   By compile-time type, I mean that the type of an object is only
>   known by the compiler during compilation -- at run-time, there
>   are no flags (or the like) attached to data marking its type.
>   Manifest types refer to objects which do have such flags indicating
>   type.  As an example, Lisp objects will have bits associated with
>   them indicating whether they're atoms, lists, etc.
>       Since I believe both type-systems have advantages, I'm curious
>   to see if any languages have tried getting the benefits of both.
>
>No preference for posting responses vs. personal E-mail.
>
>Thanks "in advance",
>---  Rich Wagner

Luca Cardelli's language Amber, a direct descendant of ML, provides for
an elegant scheme of associating a type with a value at run time in such a
way that strong typing is preserved.  Objects with a type attached are called
``dynamics'' because they have a dynamically (rather than statically) determined
type.  Amber successfully combines polymorphism, type inference, type inheritance
(as in Smalltalk), and dynamic types into a single well--defined, manageable
type system.

Bob Harper

UUCP:	... mcvax!ukc!{hwcs,kcl-cs,ucl-cs,edcaad}!cstvax!bob
ARPA:	bob%cstvax.ed@ucl-cs.arpa
tel:	+44 31 667 1081 ext. 2697
mail:	Department of Computer Science, University of Edinburgh, The King's
	Buildings (JCMB), Mayfield Road, Edinburgh EH9 3JZ, Great Britain



-- 
Bob Harper

UUCP:	... mcvax!ukc!{hwcs,kcl-cs,ucl-cs,edcaad}!cstvax!bob
ARPA:	bob%cstvax.ed@ucl-cs.arpa
tel:	+44 31 667 1081 ext. 2697
mail:	Department of Computer Science, University of Edinburgh, The King's
	Buildings (JCMB), Mayfield Road, Edinburgh EH9 3JZ, Great Britain