Skip to content

Instantly share code, notes, and snippets.

@johnynek
Created June 18, 2013 04:29
Show Gist options
  • Save johnynek/5802681 to your computer and use it in GitHub Desktop.
Save johnynek/5802681 to your computer and use it in GitHub Desktop.
An example showing how to make a function that takes one of many input types.
// Taken from: http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html
object HListTest {
sealed trait HList
final class HNil extends HList {
def ::[T](v : T) = HCons(v, this)
}
val HNil = new HNil()
final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
def ::[T](v : T) = HCons(v, this)
}
type ::[H, T <: HList] = HCons[H, T]
trait Applier[L,T] {
def apply(t: T, l: L): Option[String]
}
implicit def nilApp[T]: Applier[HNil, T] = new Applier[HNil, T] {
def apply(t: T, l: HNil) = None
}
implicit def headApp[H, R <: HList,T](implicit ev: T <:< H): Applier[HCons[(H => String),R], T] =
new Applier[HCons[(H => String),R], T] {
def apply(t: T, l: HCons[(H => String),R]) = Some(l.head.apply(t))
}
implicit def tailApp[H, R <: HList,T](implicit rapp: Applier[R,T]): Applier[HCons[H,R], T] =
new Applier[HCons[H,R], T] {
def apply(t: T, l: HCons[H,R]) = rapp(t, l.tail)
}
def applyFn[L <: HList,T](t: T, list: L)(implicit ap: Applier[L,T]): Option[String] = ap(t, list)
}
import HListTest._
val fn1 = { x: Int => x.toString }
val fn2 = { s: Symbol => s.toString }
val listFn = fn1 :: fn2 :: HNil
println(applyFn(1, listFn))
println(applyFn('x, listFn))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment