Skip to content

Instantly share code, notes, and snippets.

@mtranter
Created December 4, 2017 21:14
Show Gist options
  • Save mtranter/1bf3db05badcd2528f9ca255005ee5d2 to your computer and use it in GitHub Desktop.
Save mtranter/1bf3db05badcd2528f9ca255005ee5d2 to your computer and use it in GitHub Desktop.
Scala Type Safe Configuration with Type Level Programming
import SharedStreamsCfg._
object SharedStreamsCfg {
abstract class HasConfig
case object Y extends HasConfig
case object N extends HasConfig
type Loaded = Y.type
type NotLoaded = N.type
def apply()= new SharedStreamsCfg[NotLoaded, NotLoaded, NotLoaded] ("", 0,0)
}
case class SharedStreamsCfg[
HasName <: HasConfig,
HasAge <: HasConfig,
HasDob <: HasConfig](name: String, age: Int, dob: Long) {
def withName(name: String) = SharedStreamsCfg[Loaded, HasAge, HasDob](name, this.age, this.dob)
def withAge(age: Int) = SharedStreamsCfg[HasName, Loaded,HasDob](this.name, age, this.dob)
def withDob(dob: Long) = SharedStreamsCfg[HasName, HasAge, Loaded](this.name, this.age, dob)
}
object AppDemo {
// Only works with fully loaded config
def runApp(cfg: SharedStreamsCfg[Loaded, Loaded, Loaded]) = {
println(s"Can only use fully loaded config $cfg")
}
val cfg = SharedStreamsCfg() //SharedStreamsCfg[NotLoaded, NotLoaded, NotLoaded]
// Compile time error
// runApp(cfg)
val withName = cfg.withName("Oliver") //SharedStreamsCfg[Loaded, NotLoaded, NotLoaded]
// Compile time error
// runApp(withName)
val withNameAndAge = withName.withAge(69) //SharedStreamsCfg[Loaded, Loaded, NotLoaded]
// Compile time error
// runApp(withNameAndAge)
val fullyConfigured = withNameAndAge.withDob(313189942000l) //SharedStreamsCfg[Loaded, Loaded, Loaded]
// Compiles!
runApp(fullyConfigured)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment