Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type Constructor as Return Type

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?

like image 499
Kevin Meredith Avatar asked Jun 03 '15 14:06

Kevin Meredith


1 Answers

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.

like image 186
bheklilr Avatar answered Sep 20 '22 15:09

bheklilr