I think it’s actually going to be easier than I feared.
~ Me, writing Famous Last Words
Uh, yeah. So it turns out it won’t actually be that easy. Instead of just plugging things in straightforwardly, it turns out that I’m going to need to take a tangent to kinda overhaul the classes that represent Effes types.
Here’s the problem. Let’s say I do something like this:
b : Something[Boolean] case b of: Something[True]: doSomethingWith b c: doSomethingElseWith c
… then I want two things to happen. Firstly, in
doSomethingWith b, I want the type system to know that
b : Something[True]. And secondly, in
doSomethingElseWith c, I want the type system to know that
c : Something[False] | Nothing.
Neither one of those work today, because of an implementation choice I made a while back. To simplify recursive types like
Cons[T](head: T, tail: Cons[T] | Empty), I separated each type’s name from its argument. One bit of information says “I’m a
Cons with a generic param
T” , and a separate class holds the information “given a
Cons[E], I can tell you that its arguments are
(E, Cons[E] | Empty).”
This means that there’s no place to store the information that in some particular case, the arguments are
(T, Empty) (i.e., that this cons represents the last item of a list). That’s exactly the kind of information that the pattern matching can and should provide.
So, before I go further with the pattern matching, I’m going to have to redo my type registration quite a bit: I’m going to need to remove my “arguments for each type” registry altogether and put that information in the types themselves.