Skip to content

Instantly share code, notes, and snippets.

@propensive
Created January 31, 2015 20:03
Show Gist options
  • Save propensive/80749ef7cb347a3720ef to your computer and use it in GitHub Desktop.
Save propensive/80749ef7cb347a3720ef to your computer and use it in GitHub Desktop.
Easy Heterogeneous Varargs in Scala
// Define the general Arg type and companion object:
import language.higherKinds, language.implicitConversions, language.existentials
object Arg { implicit def toArg[Tc[_], T: Tc](t: T): Arg[T, Tc] = Arg(t, implicitly[Tc[T]]) }
case class Arg[T, Tc[_]](value: T, typeclass: Tc[T])
// Say, for example we have a typeclass for getting the length of something, with a few instances
trait Lengthable[T] { def length(t: T): Int }
implicit val intLength = new Lengthable[Int] { def length(i: Int) = 1 }
implicit val stringLength = new Lengthable[String] { def length(s: String) = s.length }
// Now, define our varargs method:
def getLengths(args: (Arg[T, Lengthable] forSome { type T })*) =
args.map { case a: Arg[t, Lengthable] => a.typeclass.length(a.value) }
// Then, here it is being used in user code:
getLengths(1, "foo") // Works
getLengths(123, 'x') // Doesn't work - no `Lengthable` for `Char`
@lolgab
Copy link

lolgab commented Mar 22, 2019

Hi, very nice code, How can I modify it to work with a typeclass taking two parameters? I have a sort of trait Conversion[From, To] typeclass..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment