Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is Scala's counterpart of Discriminated Union in F#?

Tags:

scala

f#

How would one go about transforming an Discriminated Union in F# to Scala:

type Expr =     | Val     of String     | Integer of Int32     | Lower   of Expr * Expr     | Greater of Expr * Expr     | And     of Expr * Expr     | Or      of Expr * Expr 

There is a similar post talking about ADTs in F# and Scala, but that doesn't seem to be what I am after.

like image 955
John Smith Avatar asked Sep 14 '11 07:09

John Smith


People also ask

How is a discriminated union defined?

Discriminated unions are useful for heterogeneous data; data that can have special cases, including valid and error cases; data that varies in type from one instance to another; and as an alternative for small object hierarchies. In addition, recursive discriminated unions are used to represent tree data structures.

What is a union in F#?

In F#, a sum type is called a “discriminated union” type. Each component type (called a union case) must be tagged with a label (called a case identifier or tag) so that they can be told apart (“discriminated”). The labels can be any identifier you like, but must start with an uppercase letter.


2 Answers

This is done with inheritance in scala (maybe unfortunately as it is more verbose)

sealed trait Expr case class Val(s: String) extends Expr case class Integer(i: Int) extends Expr case class Lower(left: Expr, right: Expr) extends Expr case class Greater(left: Expr, right: Expr) extends Expr ... 

You could type further

sealed trait Expr[A] case class Val(s: String) extends Expr[String] case class Integer(i: Int) extends Expr[Int] case class Lower[X](left: Expr[X], right: Expr[X])(implicit val ordering: Ordering[X]) extends Expr[Boolean] 

pattern matching with

def valueOf[A](expr: Expr[A]) : A = expr match {    case Val(s) => s    case Integer(i) => i    case l @ Lower(a,b) => l.ordering.lt(valueOf(a), valueOf(b))    ... } 

valueOf would probably be better as a method in Expr

sealed trait Expr[A] {def value: A} case class Val(value: String) extends Expr[String] case class Integer(value: Int) extends Expr[Int] case class Lower[X: Ordering](left: Expr[A], right: Expr[A]) extends Expr[Bool] {    def value = implicitly[Ordering[X]].lt(left.value, right.value) } ... 
like image 57
Didier Dupont Avatar answered Sep 22 '22 10:09

Didier Dupont


I totally agree with Didier Dupont, but if you need higher level of abstraction, implementation of the option type in Scala gives a good intuition:

sealed trait Option[+E]  case class Some[+E]( element : E ) extends Option[E] case object None extends Option[Nothing] 

Source: https://mauricio.github.io/2013/12/25/learning-scala-by-building-scala-lists-part-3.html

like image 34
Vitaliy Prooks Avatar answered Sep 22 '22 10:09

Vitaliy Prooks