mlhaufe / brevity

Brevity is a library that enables Feature-Oriented Programming (FOP) and solves the expression problem in a manner that makes data and operation declarations trivial to define and compose.
GNU Affero General Public License v3.0
1 stars 0 forks source link

Subtyping of algebraic data types #47

Open mlhaufe opened 1 year ago

mlhaufe commented 1 year ago

In Scala it looks like this:

sealed trait Point2D
case class Cartesian2(x: Double, y: Double) extends Point2D
case class Polar2(r: Double, theta: Double) extends Point2D

sealed trait Point3D extends Point2D
case class Cartesian3(x: Double, y: Double, z: Double) extends Cartesian2(x, y) with Point3D
case class Polar3(r: Double, theta: Double, z: Double) extends Polar2(r, theta) with Point3D

In this example, Cartesian3 and Polar3 are defined as case classes that extend the Cartesian2 and Polar2 case classes, respectively. They also mix in the Point3D trait, which extends the Point2D trait. This allows us to use Cartesian3 and Polar3 values wherever Point3D or Point2D values are expected.

In Brevity this could look like:

const Point2D = data({
  Cartesian2: { x: Number, y: Number },
  Polar2: { r: Number, theta: Number }
})

const Point3D = data({
  [extend]: Point2D,
  Cartesian3: { [extend]: Point2D.Cartesian2, x: Number, y: Number, z: Number },
  Polar3: { [extend]: Point2D.Polar2, r: Number, theta: Number, z: Number }
})
mlhaufe commented 1 year ago

How are anonymous declarations extended?

mlhaufe commented 1 year ago

Another interesting use case:

const Monoid = data((Monoid, T) => ({
  Unit: T,
  Merge: { left: T, right: T }
}))

const List = data((List, T) => ({
  [extend]: Monoid(T),
  Nil: { 
    [extend]: Monoid(T).Unit 
  },
  Cons: {
    [extend]: Monoid(T).Merge,
    head: T, tail: List(T)
  }
}))

https://wiki.haskell.org/Monoid https://wiki.haskell.org/Foldable_and_Traversable