Hacker News new | ask | show | jobs
by lmm 2962 days ago
That's the only way I've ever seen it implemented. If you're proposing some idea for having null in the type system as a normal type (that doesn't boil down to just being equivalent to Option/Maybe), can you be more concrete?
1 comments

Being able to create arbitrary union types between different types, like crystal (which I work on). The difference between that and option/maybe is that it ends up playing nicely with flow typing without any special cases for optional/maybe in the flow typing.
You shouldn't need special cases for optional/maybe in the first case; optional/maybe are simple sum types, you would want whatever flow-typing system you have to do the right thing with user-defined "x or y or z" types, and if you do that then it'll automatically work just as well for optional/maybe.

(I don't like inclusive union types because they're noncompositional - code you write with them isn't parametric any more - which seems particularly awkward in a compiled language - how do you compile code that forms unions involving type parameters?)

You shouldn't be able to use a type without giving all the necessary type parameters, so you can't form a union type with unbound type parameters in so it's not a problem? I'm not 100% sure what you're asking...

I'm not 100% sure how you can integrate sum types with a flow-typing system, perhaps with pattern matching?

> You shouldn't be able to use a type without giving all the necessary type parameters, so you can't form a union type with unbound type parameters in

So inside the body of a generic method (or class) you can't form unions involving the method's type parameters? That works but makes them much less useful as a language feature - most language features work as normal within a generic method.

> I'm not 100% sure how you can integrate sum types with a flow-typing system, perhaps with pattern matching?

Whatever you do for union types should work, surely. Indeed it ought to be simpler since you have more information to work with - with a sum type if the thing is B then you know it's not A, whereas with a union type it's possible for the thing to be both A and B.

In crystal, the compiler always knows the concrete values of the type parameters of any generic before typing it. I really am interested in knowing more about what you said about union types being non compositional because I'm definitely not a type theorist. The crystal compiler wasn't written by type theorists and the typing algorithm is completely home-grown.

And regarding sum types I was just thinking syntactically instead of in terms of the type system.

> In crystal, the compiler always knows the concrete values of the type parameters of any generic before typing it.

Hmm. Does that mean you can't have a generic method in a separate compilation unit from where it gets used?

> I really am interested in knowing more about what you said about union types being non compositional because I'm definitely not a type theorist.

I'm not really a type theorist, I'm just thinking about e.g. if you have a method like:

    def doSomething[A](userSuppliedValue: A) = {
      val x = if(someCondition) Some(userSuppliedValue) else None
      x match {
        case Some(a) => y ...
        case None => z ...
      }
      x match {
        case None => v ...
        case Some(a) => w ...
      }
    }
then the compiler knows that if we take branch y we will also take branch w and if we take branch z we will also take branch v. Whereas if you do the same thing with an inclusive union type, that's true most of the time but not when userSuppliedValue is null.