Skip to content

Instantly share code, notes, and snippets.

@igstan
Last active January 2, 2016 19:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igstan/8347852 to your computer and use it in GitHub Desktop.
Save igstan/8347852 to your computer and use it in GitHub Desktop.
// The main idea with type-directed lookup is that argument values are
// looked up in a scope formed by appending the members in the companion
// object of the declared param type to the normal lexical scope.
//
// It is very similar to how implicit declarations in a companion-object
// are automatically addded to the implicit scope.
//
// Start reading from the `main` function. It's probably easier to follow
// the code.
object TypeDirectedLookup {
trait CssValue {
val value: String
}
case class CssColor(value: String) extends CssValue
case class CssProperty(name: String, value: String) {
override def toString = s"$name: $value"
}
case class CssName[V <: CssValue](name: String) {
def :=(cssValue: V): CssProperty = CssProperty(name, cssValue.value)
}
// Make some factory functions available to type-directed lookup.
object CssProperty {
val color = CssName[CssColor]("color")
val backgroundColor = CssName[CssColor]("background-color")
}
// Make some factory functions available to type-directed lookup.
object CssColor {
def rgb(r: Int, g: Int, b: Int): CssColor = CssColor(s"rgb($r, $g, $b)")
def hex(h: String): CssColor = ???
def hex(h: Int): CssColor = ???
}
// When this method will be used, values in argument position may be
// resolved as members of the CssProperty's companion object.
def div(properties: CssProperty*): String = {
val declarations = properties.mkString(";\n ")
s"""div {\n $declarations;\n}"""
}
def main(args: Array[String]): Unit = {
// #1
div(CssProperty.backgroundColor := CssColor.rgb(0,0,0))
// #2
{
import CssColor._
import CssProperty._
div(backgroundColor := rgb(0,0,0))
}
// #3 type-directed lookup; won't compile because `color` and
// `backgroundColor` are not in scope.
div(
color := rgb(0,0,0),
backgroundColor := rgb(0,0,0)
)
// The previous call is conceptually similar to this desugaring.
val css = div(
({ import CssProperty._; color }) := ({ import CssColor._; rgb(0,255,0)}),
({ import CssProperty._; backgroundColor }) := ({ import CssColor._; rgb(0,0,0)})
)
println(css)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment