Does sum type have short denotation in Scala?
For example:
Product type -(Integer, Double)
Funtion type -(Integer=>Double)
Sum type -?
Does sum type have short denotation in Scala?
For example:
Product type -(Integer, Double)
Funtion type -(Integer=>Double)
Sum type -?
No, there is no syntactic sugar for defining sum types in Scala. In fact, Scala does not have sum types in its type system as a distinct feature. They need to be encoded somehow, the most widely-used encoding is as closed subtyping hierarchies, i.e. the sum type
A = B + C
is encoded as
sealed trait A
final class B extends A
final class C extends A
Note that Scala also does not have syntactic sugar for product types either. The syntax you mentioned is for tuple types, not product types. Tuple types are merely one of many different classes of product types. E.g. case class
es are another class of product types.
Note also that Scala does not have a notion of product types in its type system either. They are encoded as parametric types that are subtypes of one of the ProductN
types. I.e. the tuple type (A, B)
is actually syntactic sugar for
Tuple2[A, B]
which is defined as
final case class Tuple2[+A, +B](_1: A, _2: B) extends Product2[A, B] with Product with Serializable
Of course, classes and traits can be seen as variants of records, so in some sense, every type in Scala can be seen as a product type, which is why it is so easy to encode them.
In Scala, the sum type constructor is given by scala.util.Either
. If you need tagged sum of more than two types (e.g. A
, B
, C
), then it usually makes sense to create a custom sealed trait:
sealed trait AorBorC
case class CaseA(a: A) extends AorBorC
case class CaseB(b: B) extends AorBorC
case class CaseC(c: C) extends AorBorC
and then work with pattern matching.
You can of course define shortcuts, if you want:
type +[A, B] = Either[A, B]
type \/[A, B] = Either[A, B]
and then use them in infix notation A + B
or A \/ B
.
You can also use \/
from ScalaZ.
The util.Either
is indeed the coproduct as explained here:
A, B
, you can form the type Either[A, B]
(there are no restrictions)a: A
and b: B
, then both Left(a)
and Right(b)
are values of type Either[A, B]
.Elimination: if e: Either[A, B]
, then the usual pattern matching can be used to collapse both cases to a single type C
:
e match {
case Left(a) => c1(a) // assuming `c1(a): C`
case Right(b) => c2(b) // assuming `c2(b): C`
}
There is also fold
:
e.fold(c1, c2)
which does essentially the same, and also produces a value of type C
. The meaning should be clear:
Left(a).fold(c1, c2) == c1(a)
Right(b).fold(c1, c2) == c2(b)
This is indeed the sum type of A
and B
, because for any other type C
and any two functions c1: A => C
, c2: B => C
there is the function (e: Either[A, B]) => e.fold(c1, c2)
, for which the above two identities hold, which is exactly the universal property required by the definition of a coproduct.