Austral doesn’t have operator overloading. That is, you can’t write:
function foo(x: Int32): Unit;
function foo(x: Buffer): Int32;
Because the compiler will complain that there are two functions with the same
name. But suppose we want to print things. Normally, we’d have to define a
printT
function for each type T
. This works, it’s not too verbose, but it
doesn’t let you reason about interfaces: to know if a type is printable, you
have to manually look for a function called something like printFoo
for the
type.
Type classes let us have operator overloading in a way that is principled and allows us to reason about interfaces.
A type class is an interface that types can implement, equivalently, it defines the set of types that implement that interface. Type classes have instances: an instance is the implementation of a type class for a particular type.
For example, you could have a type class for types that can be printed:
typeclass Printable(T: Type) is
generic [R: Region]
method printRef(ref: &[T, R]): Unit;
end;
And here’s how you would define an instance for the Int64
type:
instance Printable(Int64) is
generic [R: Region]
method printRef(ref: &[Int64, R]): Unit is
-- ...
end;
end;