Types in Mondrian


The Mondrian design tackles the mismatch between traditional functional language type systems and that of the CLR by identifying ways of mapping the former onto the later. A syntax has been defined that looks familiar to the object-oriented CLR programmer, so that task of interlanguage working is simplified.

In the following discussions, we visualize CLR code fragments by using C#. Although using CLR Intermediate Language (IL) would be more language-neutral, C# is far easier to read yet still follows the CLR model closely.

Primitive Types

Primitive types appear in all languages in much the same way, and Mondrian is no different. Unusually for a functional language, Mondrian directly supports strings through the CLR primitive System.String type. However, the more typical "list of characters " model for strings is, of course, provided in Mondrian and standard functions to convert between the two models are provided.

The CLR provides both value ("unboxed") and reference ("boxed") versions of primitive types. To easily support parametric polymorphism, functional language implementations often restrict themselves to reference versions of primitive types, and this is the approach we have taken with Mondrian. Other CLR-hosted languages' code must therefore box values of primitive types when calling Mondrian code. Doing this is usually easy; indeed, the C# language handles it automatically so programmers never need be concerned with it.

Type Products

The product, or tuple, type is widely used in functional languages. For example, a type for a coordinate might be expressed in Haskell as

 type Coord = (Float, Float) 

or alternatively by a record declaration such as

 data Coord = Cd { x, y :: Float } 

An equivalent of both of these in the CLR type system is a field-only class:

 class Coord { Float x; Float y; } 

The mapping is straightforward and could be used by functional languages running on the CLR. However, to reduce the apparent gap between Mondrian and other languages running on the CLR, we chose to use the class construct directly.

The use of the class construct also simplifies accessing objects that have been created by other CLR-hosted languages. Any CLR object can be viewed as a product and its fields accessed, just as with Mondrian-created products. However, to access the methods of a CLR object from a functional language requires a different mechanism; this need is addressed later in the discussion of interlanguage calling.

Field-only classes are not commonly used by object-oriented programmers. Usually, at least a constructor method is defined, and often access methods, to separate the interface and implementation. Rather than direct field access, it is expected that Mondrian programs will provide access functions and these will be used by other languages. Access methods are, of course, good object-oriented programming style, so defining and using them is not an issue. They have additional benefits when integrating functional and nonfunctional languages on the CLR, as explained later.

Type Unions

Tagged unions are central to functional languages. They provide for both simple enumeration types and more complex variant and recursive types. The key role of tagged unions is reflected in the provision of pattern matching to provide simple and concise access to their components . For example, in Haskell a list of integers can be expressed as follows:

 data IntList = Nil  Cons Integer IntList 

A Haskell function to determine the length of an IntList might be defined as

 length Nil = 0  length Cons h t = 1 + length t 

or equivalently as

 length l = case l of             {  Nil      -> 0;               Cons h t -> 1 + length t            } 

Union types are not provided by the CLR type system; rather, subtyping through a class inheritance mechanism is provided. A rough equivalent of the union type can be modeled in the class/subclass model by defining an abstract class to represent the type, together with one subclass for each of the variants. For example, IntList could be modeled in C# as follows:

 abstract class IntList {};  class Nil extends IntList {}; class Cons extends IntList {   head: Integer;     tail: IntList; }; 

These two models are not equivalent: The union type provides only a single level of variants and the number of variants is fixed. In the subtyping model, it is possible both to subclass the variants, creating a multilevel tree of variants, and to extend the number of variants. The consequence is that not all type hierarchies of CLR classes can be viewed as tagged unions by functional languages such as Haskell.

The Mondrian design addresses this lack of equivalence by using the class/subclass formulation directly. It produces a more flexible type system than traditional functional languages while also increasing the compatibility with other CLR-hosted languages.

Mondrian, following its minimalist approach, also provides pattern matching through its switch expression. Only one level of matching is supported ”for example, patterns such as " Cons h1 (Cons h2 t) ", which would be valid in Haskell, are not supported. The length function given earlier might be written in Mondrian as follows:

 length = l -> switch(l)                {  case Nil            : 0;                  case Cons{t = tail;}: 1 + length t;               } 

Parametric Types

In a functional language, our list example would usually be defined using a parametric type that can represent lists of any type. For example:

 data List a = Nil  Cons a (List a) 

In Haskell this type represents an homogenous list ”that is, all members of the list will be of the same type. Uses of parametric types are checked at compile time.

The CLR does not support parametric types, an issue noted by others in the context of nonfunctional languages [9]. A standard object-oriented approach to providing something similar to parametric types is based on the existence of a unique supertype , called Object in both Java and C#, for all classes. Using this supertype, heterogeneous generic types may be defined. For example, a list could be defined as follows:

 class ListNode  {   Object head;     ListNode tail; }; 

Parametric types are very important in the functional programming model, being a key constituent of the higher-order programming that gives the paradigm much of its expressive power. Given this importance, parametric types are directly supported by Mondrian. However, the syntax adopted is a more object-oriented style:

 abstract class List<a> {};  class Nil<a> extends List<a> {}; class Cons<a> extends List<a> {   head : a;     tail : List<a>; }; 

Types such as these can be statically checked, using the same methods as found in traditional functional languages. This means, for example, that a List value is guaranteed to be homogenous and type casts are never needed; indeed, Mondrian does not provide type casts at all. However, when viewed from another CLR-hosted language, the type parameters will not exist, and the Object type will appear instead:

 abstract class List {};  class Nil extends List {}; class Cons extends List {   head: Object;     tail: List; }; 

To other CLR languages, values of this List type are not guaranteed to be homogenous, and uses of head may need to be cast to the appropriate type:

 Integer anInt;  Cons node; node.head = anInt; // OK anInt = (Integer)node.head; // cast required 

This is the standard object-oriented programming style when dealing with heterogeneous types. Thus, the Mondrian design succeeds in presenting an appropriate model to both the functional and the nonfunctional programmer.

NOTE

Implementation-oriented readers will notice that there is a hidden cost in supporting Mondrian's parametric types on the CLR. In a traditional functional language, implementation parametric types are checked at compile time. In our CLR implementation, uses of parametric types are checked at runtime. This is not a drawback of Mondrian per se, as this cost is paid by all CLR-hosted languages when generic structures are created. Should direct support for generics be added to the CLR (as proposed, for example, by [9]), then this would benefit Mondrian along with other CLR-hosted languages. For more details on Mondrian implementation issues, see [1].




Programming in the .NET Environment
Programming in the .NET Environment
ISBN: 0201770180
EAN: 2147483647
Year: 2002
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net