Hacker News new | ask | show | jobs
by yummyfajitas 4118 days ago
I can't speak about OCaml, but Haskell doesn't have subtypes. That's where a lot of the complexity of Scala comes from as well as being a source of annoying bugs:

    def f(x: Int) = if (x % 2 == 0) { x } else { None }
(This compiles, but the type of `f` is not `f: Int => Option[Int]`.)

[edit: the bug is not in the scala compiler, the bug is in my code - I almost certainly did not want `f` to have type `Int => Any`. My phrasing, now edited, was misleading. ]

3 comments

That is not a bug. That is subtype inference working correctly. If you (mistakenly) expected the return type of f to be Option[Int], say so, and you'll get a compile time error telling you about your mistake:

scala> def f(x: Int): Option[Int] = if (x % 2 == 0) { x } else { None } <console>:7: error: type mismatch; found : Int required: Option[Int] def f(x: Int): Option[Int] = if (x % 2 == 0) { x } else { None }

    scala> def f(x: Int) = if (x % 2 == 0) { x } else { None }
    f: (x: Int)Any
Which is expected. The only shared type between both branches of the `if` expression is `Any`.
This is correct given Scala's limitation: the only common supertype between Int and Option is Any.

A language that supports union types (e.g. Ceylon) will type this expression as Int|Option[Int], which is as specific as you can get.

I believe Ceylon will actually further refine Int | Option[Int] to simply Option[Int].

Option[Int] is simply an alias to the type Int | Null, so Int | Option[Int] would become Int | Int | Null after replacement, which simplifies to Int | Null since Int | Int is equivalent to just Int.