I mentioned built-in types (aka primitives) in my last post. It turns out, pattern matching lets Effes be a bit more expressive than the standard “here’s an int, go do int things with it” operations. For instance, imagine a world where divide-by-zero exceptions can’t happen! (Big disclosure: I don’t think I’ve ever actually triggered one, so they’re not actually that big a deal to me. Still, I like the idea of getting rid of them at compile time.)
Integers in Effes work something like this:
type Int = IntZero | InvValue type IntValue @builtin: + (other: Int) -> Int: @builtin - (other: Int) -> Int: @builtin * (other: Int) -> Int: @builtin / (other: IntValue) -> Int: @builtin type IntZero: @builtin ...
As you can see, there are actually two int primitives, one for zero and one for everything else.
Int is just an alias for the disjunction of those two types, and most of the basic math operations take two Ints (
other). Division is the exception: the denominator must be an
IntValue specifically. That means it can’t be an
IntZero — and thus that divide-by-zero errors are caught at compile time.
Here’s how you’d use it:
hitsPerMinute = case minutes of IntZero: Error -- or whatever IntValue: hits / minutes
In this snippet,
minutes comes in as a standard
Int. We can’t divide by
Int, so we throw
minutes into a
case expression. If
minutes is an
IntZero, the result is explicitly some sort of error; if it’s
IntValue, we can divide by it.
I’m still not sure if I want to do any such trickery for other primitives. I think I won’t, because other primitives don’t have operations that are undefined (ie, throw an exception) for certain inputs. Floating points, for instance, let you divide by zero, add infinity, or do anything else and always get a value back. It may be
NaN, but it’s still a value.
It’s actually a bit interesting to me that other languages don’t have this sort of behavior; all you really need to make it work is pattern matching. My guess is that it’s just not a very compelling problem (as I mentioned earlier, I don’t think I’ve ever actually gotten tripped up by it), so it’s not worth the work to catch it. Effes’ type scheme lets me catch it with minimal compiler trickery, which is probably about as much as it’s worth.