The utility of type models is that they are smaller than models in which a general computation can be supported. This means that they can serve a useful purpose in predicting whether an error will occur.
In Computer Science, types serve two major purposes:
In their first role, type-systems can be regarded as a kind of weak logic, capable of inferring that certain events, called type-errors cannot occur. The most important property of a type system is that type-correctness of a program must be decidable. From this requirement, it is clear that not all errors are type-errors, since failure of a program to terminate should clearly be regarded as an error, but the halting problem is undecidable.
If we want to examine the idea of a type-system from the point of view of Combinatory Models, the natural approach is to introduce the idea of a set of exceptions in the model. If an expression can evaluate to an exception, then it should be regarded as erroneous.
EX1 ( d) = for
EX2 (d ) = for
K c x = c
S f g x = (f x) (g x)
We denote the type of procedures of by Proc().
If d , we say that d has the (weak) type TD TR if d TD TR.
It should be noted that given our existing type-descriptive apparatus no unique procedure-type can be ascribed to a procedure. For a given procedure object d it is possible that p TD1 TR1 and also p TD2 TR2 where there is way of expressing these two relationships in the form of p TD3 TR3 without losing useful discriminatory power. For example, the absolute value procedure in the FSM has among its types:
But the second of these statements does not subsume the first, because the first statement tells us the relevant fact that if we give abs an integer as argument it returns an integer as result.
If TD1, TD2, TR1, TR2, are types for which TD2 TD1 and TR1 TR2, then
Let p TD1 TR1 . Then (p d1) TR1 for all d1 TD1 .
But TD2 TD1. Hence for all d2 TD2, (p d2) TR1. Since however TR1 TR2 , we see that (p d2) TR2 .
Thus we have shown that any p TD1 TR1 maps TD2 to TR2, thus establishing our lemma.
A consequence of the contravariance rule is that, for example, despite the fact that Integer Number, the type Integer Integer is not contained in the type Number Number. Thus, for example, the intersection
is non-redundant.
A simple converse of these two lemmas is clearly not true of all combinatory algebras. for consider a combinatory algebra without procedure objects. Then TD TR is always the empty-set for any TR which contains no exceptions, so that TD1 TR1 TD2 TR2 is true for any combinatory algebras and ranges whatever.
Since the combinators are denizens of every combinatory algebra, let's start with their type.
Let t T. Then I t = t. Thus I TT.
It is sufficient to show that if f T1 T2 T3 then (S f) (T1 T'2) T1 T3
Hence it suffices to show that if, in addition, g T1 T'2 then (S f g) T1 T3 .
Hence it suffices to show that if, in addition, x T1 then S f g x T3 .
But S f g x = (f x) (g x). Since x T1 , and f T1 T2 T3 , it follows that (f x) T2 T3. Likewise (g x) T'2. But T'2 T2 , so that ((f x) (g x)) T3 . Hence (S f g x) in T3 , hence (S f g) in T1 T3 , hence (S f) (T1 T'2) T1 T3 , hence
One interpretation of the above results is that a particular type for one of the combinators is as an intersection. For example, for any two types T1 and T2:
And in general, for any family (Tj) of types:
This is quite easily realised in a simple applicative algebra. For example, consider an algebra which has the Scheme integers and floats, together with the abs procedure, which takes the absolute value of a number. Then we can take Integer, Float, {abs}, as separate types, obtaining a finite applicative algebra:
(Integer Integer) =
(Integer Float) =
(Float Float) =
(Float Integer) =
({abs} Integer) = Integer
({abs} Float) = Float
({abs} {abs}) =
A projection mapping always induces a partition of its domain into pairwise disjoint sets whose union is the whole domain.
Let ti, t'i Ti and tj, t'j Tj Let (ti tj) . Tk. Then (ti t'j) Tk by HM1, and hence (t'i t'j) . Tk by HM2. Thus the operation is well-defined.
Given a congruence partition of an applicative algebra, where d Ti we write [[d]] for Ti. Thus from definition CP we see that
Suppose our applicative algebra is a combinatory algebra. Then it is easy enough to extend the above lemma to show that a congruence partition of our combinatory algebra is itself a combinatory algebra. Since K and S are defined equationally, the following lemma is an instance of a well known theorem of Universal Algebra. However, we give here an elementary proof.
([[S]] [[d1]] [[d2]] [[d3]]) = [[(S d1 d2 d3) ]]
= [[(d1 d3) (d2 d3) ]] = [[((d1 d3) (d2 d3))]]
= (([[d1]] [[d3]]) ([[d2]] [[d3]]))
To extend these ideas to a combinatorial model we need to meet the " conditions" of the combinatory model. But these are not equational, and so are not automatically satisfied by the idea of congruence as defined, just as for example the quotient of an integral domain by an ideal is not necessarily an integral domain. Saying "there are no divisors of zero" is not an equational statement. Thus while the integers form an integral domain, the ring of integers modulo six has divisors of zero, namely [[3]] and [[2]].
We can approach this problem from another point of view. Let's introduce the idea of monomorphic procedure types
The concept is of course too restrictive to serve to characterise all of the types of SML procedure, which are parametrically polymorphic. It' also too restrictive to characterise the S, K, I combinators which are likewise parametrically polymorphic. But it does give us a start in letting us create an applicative algebra of types with a simple definition of the operator, and which is extensional with respect to its procedure-types.
Thus TD1 and TD2 have an element in common, and being members of the partition, TD1= TD2
Also p d TR1 and p d TR2, since . d TD1 and d TD2. Thus TR1, TR2 have an element in common, and being members of the partition, TR1= TR2
Hence the result.
It is not hard to construct monomorphically partitioned applicative algebras with a finite collection of procedure objects, and a finite partition. But adding combinators gives rise to an infinite collection of procedure objects, which require an extension of the idea of monomorphic functional types. Consider for example, the I combinator. It can take as its argument any object. However our requirement that objects be partitioned into distinct types does not allow us to have the idea of type-union, and indeed, a characterisation of I in terms of type-union is too imprecise. For, while I has the (weak) type TD TD where TD is the carrier set of , this does not capture the fact that I T T for all types T, that is to say, that I i (Ti Ti) for any family of types (Ti).