You have two types T and U, you can combine them in two ways: A(T,U) or B(T)|C(U). A simple but powerful idea that's surprisingly well suited for modeling real world constraints in a typesafe fashion.
| Some(T) type Result[T, E] = Success(T) | Error(E) type List[T] = EmptyList | Cons(T, List[T]) type Natural = Zero | Succesor(Natural) type BinaryTree[T] = EmptyTree | Node(BinaryTree[T], T, BinaryTree[T]) type Tree[T] = Tree(T, List[Tree[T]]) type Date = Date(Int, Int, Int) type Point2D = Cartesian(Double, Double) | Polar(Double, Double) type Suit = ♠ | ♥ | ♦ | ♣ type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King type PlayingCard = Joker | Card(Rank, Suit) type Shape = Circle(Point, Double) | Rectangle(Point, Point) | Polygon(List[Point]) type Expr = Plus(Expr, Expr) | Times(Expr, Expr) | LiteralNumber(Decimal) | Variable(String) type ColorName = Black | White | Red | Blue type Color = Named(ColorName) | RGB(Byte, Byte, Byte) | HSL(Degree, Percent, Percent) type TranslucidColor = TranslucidColor(Color, Percent)
♥ extends Suit case object ♦ extends Suit case object ♣ extends Suit sealed trait Rank case object Ace extends Rank case object Two extends Rank case object Three extends Rank case object Four extends Rank case object Five extends Rank case object Six extends Rank case object Seven extends Rank case object Eight extends Rank case object Nine extends Rank case object Ten extends Rank case object Jack extends Rank case object Queen extends Rank case object King extends Rank sealed trait PlayingCard case object Joker extends PlayingCard final case class Card(rank: Rank, suit: Suit) extends PlayingCard type Suit = ♠ | ♥ | ♦ | ♣ type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King type PlayingCard = Joker | Card(Rank, Suit) I HATE Inheritance Actually this is not Scala code!
Erik Meijer Erik: Maybe that's why I was having so much trouble. Brian: No, no, no. You had so much trouble because you didn't have a disciplined… you had an explosion of special cases. Erik: Yes. Brian: Instead of disciplining your cases by following proper mathematical reasoning, you just started hacking it into existence."If it's like this, then if it's like that", and you had no idea whether you exhausted all the cases. And then you had at the bottom something that says "else throw exception 'this never happens'." Erik: Yes! Brian: And how often does that happen? Erik: Actually now I have to confess something. That code should never execute, but if I do it does throw an exception. So I just commented that out. But all my unit tests pass!