You can use implicits to do something of the like:
trait TupOps[T,I] {
val size: Int
def fromList(vals: List[I]): T
}
def list2tup[T,I](vals: List[List[I]])(implicit to: TupOps[T,I]) = {
if (!vals.forall(_.size == to.size)) sys.error("wrong list size")
else vals.map(to.fromList _)
}
implicit def tup2ops[I] = new TupOps[(I,I),I] {
val size = 2
def fromList(v: List[I]) = (v(0), v(1))
}
implicit def tup3ops[I] = new TupOps[(I,I,I),I] {
val size = 3
def fromList(v: List[I]) = (v(0), v(1), v(2))
}
Invoke like this:
list2tup[(Int,Int),Int](List(List(1,2),List(2,3)))
But this is not necessarily nicer, especially because you have to write the Int
a second time, which is IMHO rather a syntax limitation, since you cannot give one type and tell the compiler to infer the other.
UPDATE
It looks almost nicer if you pass in the implicit explicitly:
list2tup(List(List(1,2),List(2,3)))(tup2ops)