archives

Type classes in a dynamic language

Hello,
I wanted to discuss my take on a "type class" concept in a dynamically typed language. The language is called Ela (http://elalang.net) and for now it lacks any way to provide a function overloading. The language itself has Haskell/ML style syntax (layout based), is strict by default (lazy by demand), it is also pure and dynamically typed. I was playing with an idea of overloading for quite some time but didn't actually come to a good solution.

So another attempt.

First of all it is quite different from regular type classes as soon as it relies on a dynamic, not static dispatch. Also it is just single dispatch for now (which somewhat logical as soon as all functions are curried).

The preview version (link below) contains three new entities. The first is a 'type' entity that creates a user type:

type user x = User x

This declaration is basically a function (and is first class therefore). The right hand can contain any expression. Here a variant (aka polymorphic variant) tag is used which simply "wraps" a given value. Variant is helpful as soon as it can be used to "unwrap" the value like so:

let (User x) = ...

The second is a 'class' entity, which is defined like so:

class Foo
  foo bar

(This syntax is probably a bit clumsy).
Ela requires that all "class members" are functions, signature is not required as soon as they are untyped. Basically a declaration like the one above creates two global functions 'foo' and 'bar' (classes are mostly ignored by the run-time). These two functions are quite different from regular functions as soon as they are organized as "vocabularies", type-indexed functions.

Having a class and a type one can create an instance of a class for a type like so:

instance Foo user
  where foo (User x) = "Foo:" ++ show x
     et bar (User x) = "Bar:" ++ show x

An instance adds these functions to the previously defined vocabularies.

These vocabularies are basically mutable objects however all instances are always executed before any user code. When implementing an instance it is required to provide an implementation for all functions in a class. It is not possible to override an existing instance (it is not a problem technically however I am not sure that this is a good feature). And of course it is possible to define instances for built-in types (such as int, double, string, list, etc.). "Class functions" also can't be shadowed by other bindings (Ela does support shadowing for regular bindings).

What do you think about such an approach?

There is a preview for this implementation. It only comes with prelude that defines several classes/instances for built-ins and other basic functions (such as composition, application operators, etc.) and REPL. Requires Mono 2.6+/.NET 2.0+, 1MB:
http://elalang.googlecode.com/files/ela-0.11-preview.zip

BTW. There's a short language reference and a side-by-side comparison with Haskell if you're interested:
http://code.google.com/p/elalang/w/list