Types
Falcon 9
Rocket Software
object RocketWithVals {
case class Rocket( o: O2, f: Fuel )
sealed trait O2
case object NoO2 extends O2
case object HasO2 extends O2
sealed trait Fuel
case object NoFuel extends Fuel
case object Fueled extends Fuel
def createRocket() = Rocket(NoO2, NoFuel) //> createRocket: ()RocketWithVals.Rocket
def addFuel(x: Rocket) = x match {
case Rocket(o, NoFuel) => Rocket(o, Fueled)
case _ => throw new IllegalStateException
} //> addFuel: (x: RocketWithVals.Rocket)RocketWithVals.Rocket
def addO2(x: Rocket) = x match {
case Rocket(NoO2, f) => Rocket(HasO2, f)
case _ => throw new IllegalStateException
} //> addO2: (x: RocketWithVals.Rocket)RocketWithVals.Rocket
def launch(x: Rocket) = x match {
case Rocket(HasO2, Fueled) => "launched!"
case _ => throw new IllegalStateException
} //> launch: (x: RocketWithVals.Rocket)String
val goodSeq = launch(addO2(addFuel(createRocket)))
//> goodSeq : String = launched!
val anotherGoodSeq = launch(addFuel(addO2(createRocket)))
//> anotherGoodSeq : String = launched!
// val badSeq = launch(addFuel(createRocket()))
// val anotherBadSeq = launch(addFuel(addO2(addFuel(createRocket()))))
}Elon does not like the exceptions.
Found http://james-iry.blogspot.com.au
Better Rocket Software
object RocketWithTypes {
case class Rocket[ O <: O2, F <: Fuel ]()
sealed trait O2
trait NoO2 extends O2
trait HasO2 extends O2
sealed trait Fuel
trait NoFuel extends Fuel
trait Fueled extends Fuel
def createRocket() = Rocket[NoO2, NoFuel] //> createRocket: ()RocketWithTypes.Rocket[RocketWithTypes.NoO2,RocketWithTypes.
//| NoFuel]
def addFuel[O <: O2](x: Rocket[O, NoFuel]) = Rocket[O, Fueled]
//> addFuel: [O <: RocketWithTypes.O2](x: RocketWithTypes.Rocket[O,RocketWithTyp
//| es.NoFuel])RocketWithTypes.Rocket[O,RocketWithTypes.Fueled]
def addO2[F <: Fuel](x: Rocket[NoO2, F]) = Rocket[HasO2, F]
//> addO2: [F <: RocketWithTypes.Fuel](x: RocketWithTypes.Rocket[RocketWithTypes
//| .NoO2,F])RocketWithTypes.Rocket[RocketWithTypes.HasO2,F]
def launch(x: Rocket[HasO2, Fueled]) = "launched!"
//> launch: (x: RocketWithTypes.Rocket[RocketWithTypes.HasO2,RocketWithTypes.Fue
//| led])String
val goodSeq = launch(addO2(addFuel(createRocket)))
//> goodSeq : String = launched!
val anotherGoodSeq = launch(addFuel(addO2(createRocket)))
//> anotherGoodSeq : String = launched!
// val badSeq = launch(addFuel(createRocket()))
// val anotherBadSeq = launch(addFuel(addO2(addFuel(createRocket()))))
}Elon likes the type safety.
You can!
JSON Parse State as a type (its recursive)
sealed trait JState trait Start extends JState trait Complete extends JState trait OpenArray[E <: JState] extends JState trait OpenObject[E <: JState] extends JState
Typesafe JSON Incremental JSON Builder
case class JBuilder[S <: JState]( buffer: B, delimit: B => B) {
def flip(b: B = empty) = (buffer, JBuilder[S](b, delimit))
def fullText(implicit bufRep: JSONRep[B]) = bufRep fullText buffer
}
implicit class ArrayOps[E <: JState](b: JBuilder[OpenArray[E]]) {
def | [T:Element] (t: T) = shift(Element[T] encode t)
...
}
implicit class ObjectOps[E <: JState]( b: JBuilder[OpenObject[E]]) {
def | [T:Element](f: (String, T)) = shift(f._1, Element[T] encode f._2)
...
}Incremental JSON Generation
object json_generator {
import au.com.langdale.json.DSL._
val p1 = JBuilder.start | array | 30.0 //> p1 : au.com.langdale.json.DSL.JBuilder[au.com.langdale.json.DSL.OpenArray[a
//| u.com.langdale.json.DSL.Complete]] = JBuilder(List(30.0, [),<function1>)
val p2 = p1 | obj | "name" -> "joe" //> p2 : au.com.langdale.json.DSL.JBuilder[au.com.langdale.json.DSL.OpenObject[
//| au.com.langdale.json.DSL.OpenArray[au.com.langdale.json.DSL.Complete]]] = JB
//| uilder(List("joe", :, "name", {, ,, 30.0, [),<function1>)
// val p3 = p2 | "element"
p2.fullText //> res0: CharSequence = [30.0,{"name":"joe"
val p4 = p2 | end | end //> p4 : au.com.langdale.json.DSL.JBuilder[au.com.langdale.json.DSL.Complete] =
//| JBuilder(List(], }, "joe", :, "name", {, ,, 30.0, [),<function1>)
p4.fullText //> res1: CharSequence = [30.0,{"name":"joe"}]
}