fourth44 / ADTFactory

Proof of Concept for assisting in creating type-safe factories for a single sealed trait family.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ADTFactory

Proof of Concept for assisting in creating type-safe factories for mapping from values of some type to values of member types of a single-level ADT. The ADT should be a sealed trait or sealed abstract class with case class members. ADTFactory makes use of Shapeless.

A concrete factory is obtained by creating a ADTFactory providing a HList of constructor types for each ADT member (InputType => Option[MemberType]). Note that the HList should be ordered alphabetically according to the type names of the members, and cannot provide any constuctor functions to types outside the ADT. Both limitations can be lifted but was not of interest for this PoC.

Example:

import shapeless._

sealed trait MyRoot { val e: String }

case class ChildA(e: String) extends MyRoot
case class ChildB(e: String) extends MyRoot
case class ChildC(e: String) extends MyRoot

implicit val generic = Generic[MyRoot]

def opt[A](pf: PartialFunction[String, A]) = pf.lift

val constructors =
  opt { case s: String if s == "one" => ChildA(s) } ::
  opt { case s: String if s == "two" => ChildB(s) } ::
  opt { case s: String if s == "three" => ChildC(s) } ::
  HNil
  
val myRootFactory = ADTFactory[String, MyRoot](constructors)

val myChildB:   Option[ChildB] = myRootFactory.createOfType[ChildB]("two")
val myNone:     Option[ChildB] = myRootFactory.createOfType[ChildB]("one")
val myUnknown:  Option[MyRoot] = myRootFactory.createAny("three")
val myNotThere: Option[MyRoot] = myRootFactory.createAny("four")

assert(myChildB == Some(ChildB("two")))
assert(myNone == None)
assert(myUnknown == Some(ChildC("three")))
assert(myNotThere == None)

About

Proof of Concept for assisting in creating type-safe factories for a single sealed trait family.


Languages

Language:Scala 100.0%