I've been using my spare time to read about different languages and how they deal with types. It's amazing how good ideas are implemented in several non-mainstream languages that are not going to ever be known by most of programmers.
Nevertheless, you can deduce that I'm working on a language. Indeed, just as a brain exercise. Fixing and improving Castle is nice and it's cool, but sometimes I need to research and try things on a different field. One of the things I wanted to make work was type inference, but the sophisticate version of type inference.
The non-sophisticate type inference is being able to type designators based on the assignment expression, like
myvar = 10 + 15
The binary expression will be evaluated to int, and so is myvar. This does not consider others usages of myvar on the same context. For example:
myvar = 1
if (myvar > 10L)
...
Here, while myvar will be typed as an int, it's being used in a comparison with a long.
There are many paper on type inference for object oriented programming languages, quite interesting subject. Most of them care about polymorphic function as a mean to achieve efficient code and thus optimized execution.
The quite trivial example would be
def max(a, b)
if (a <= b) b else a
end
max(1, 2)
max(10L, 20L)
max(3.01, PI)
Type inference will be used here to create three versions of the same max function. Some papers suggest the usage of constraints inequalities to solve types and to create the versioned functions in this case. This involve creating a graph based on code flow where the nodes represent the variables and the edges represent the constraints:
myvar = MyClass.new # Constraint: myvar should be at least as subset of MyClass type
Anyway, a very sophisticate type inference may be found on ML. The book "Programming language pragmatics" has a great topic dedicated to it. Using its example code:
fun fib (n) =
let fun fib_helper(f1, f2, i) =
if i = n then f2
else fib_helper(f2, f1+f2, i+1)
in
fib_helper(0,1,0)
end;
The syntax is quite strange, isn't it? I've never programmed in ML, neither any other functional or imperative-functional language. But the beauty here is the type inferencing working
The parameter i should be int as it's been used in a binary expression with another int. Parameter n is compared to i, so it must be int too. When fib_helper is invoked in the body of fib function, the parameter are also int, so this is consistent with the inference so far. Any usage that is not consistent will raise an error.
Isn't that cool or what?
Anyway, for now I'm going to stick with a non-sophisticated version, unless I bump into a nice paper describing a very simple algorithm that fits my needs.
Btw Nemerle is a language to be checked. I'd never use it to construct a system, but it's quite nice to force a shift in your brain. The virtualization of structural types that they achieved is impressive. If you don't know what that means, in most languages type equivalence is based on what a type have
record x
int i,j
end
record y
int age, favcolor
end
In lots of programing languages, x and y are equivalent. Java and .Net use names to determine equivalence.
On Nemerle (copying from their tutorial) they have (and you can create your own) methods that depend on a signature
class Hashtable ['a, 'b]
{
public Iter (f : 'a * 'b -> void) : void
{ ... }
}
Here Iter is a function that expects a function with the signature of 'a, 'b and returning void.
Well, there are many programming languages around. Each has distinct features and cool and nasty stuff. So my word of advice: get out of the mainstream driveway every now and then and see what's happening around. You won't regret; :-)
Btw Mike has cast his vote towards a 100% dynamic language. I'm really not convinced about that and still leaning towards a hybrid solution.