In Scala, I can define an Algebraic Data Type:
scala> sealed trait Maybe[A]
defined trait Maybe
scala> case class Just[A](x: A) extends Maybe[A]
defined class Just
scala> case object NothingHere extends Maybe[Nothing]
defined object NothingHere
It's possible to return a function, f
, with a return type of Maybe[A]
.
scala> def f[A](x: A): Maybe[A] = Just(x)
f: [A](x: A)Maybe[A]
However, it's also possible to specify that a Just[A]
is returned.
scala> def f[A](x: A): Just[A] = Just(x)
f: [A](x: A)Just[A]
Now I'll do the similar exercise in Haskell:
Prelude> data Option a = None | Some a deriving Show
Prelude> let f x = Some x :: Option Int
Prelude> f 10
Some 10
But, I can't set a return type of a type constructor.
Prelude> let f x = Some x :: Some Int
<interactive>:10:21:
Not in scope: type constructor or class `Some'
A data constructor of that name is in scope; did you mean DataKinds?
Prelude> let f x = None :: None
Is the simple difference that Scala's Just
is a class, i.e. a legitimate return type? Whereas, in Haskell, a type constructor cannot be a return type?
The difference is how Scala chose to implement ADTs. Scala uses case classes that extend a trait in an OOP style, so each case is its own type, whereas Haskell just has multiple constructors for the same type. Since they aren't separate types but essentially just separate functions, you can't distinguish them at the type level. There are extensions that give you some ability to make that type level distinction, but it won't be the same thing as what Scala has. And trying to fit Haskell's type system into Scala's type system is probably not the best of ideas.
In short, Scala approximates ADTs using a form of inheritance, whereas Haskell just has ADTs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With