Can We Wean Scala Off Implicit Conversions?

Ok let me explain some more: *: is tuple cons. So *: is like :: and EmptyTuple is like Nil. For instance, the triple type (Int, String, Boolean) is an abbreviation for Int *: String *: Boolean *: EmptyTuple. Here’s the complete example for what I had in mind:

trait Frag

case class IntFrag(x: Int) extends Frag
case class StringFrag(x: String) extends Frag

trait Fragable[T]:
  def toFrags(x: T): List[Frag]

given Fragable[Int]:
  def toFrags(x: Int) = List(IntFrag(x))
given Fragable[String]:
  def toFrags(x: String) = List(StringFrag(x))
given [A](using af: Fragable[A]) as Fragable[List[A]]:
  def toFrags(xs: List[A]) = xs.flatMap(af.toFrags)
given Fragable[EmptyTuple]:
  def toFrags(x: EmptyTuple) = Nil
given [A, B <: Tuple](using af: Fragable[A], bf: Fragable[B]) as Fragable[A *: B]:
  def toFrags(x: A *: B) = af.toFrags(x.head) ++ bf.toFrags(x.tail)

def f[T](x: T)(using tf: Fragable[T]) =
  println(s"got: ${tf.toFrags(x).mkString(", ")}")

@main def Test =
  f(1)
  f("abc")
  f(List(1, 2, 3))
  f(1, "a", List("c", "d"))
4 Likes