Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write tuple range function in scala?

I want following function range((1,1), (2,2)) which return

Seq[(Int,Int)]((1,1),(1,2),(2,1),(2,2))

It is analog for one dimensional range with 1 to 2

The function should work for any scala tuple (i.e. Tuple2, Tuple3, Tuple4, ...) and be typesafe.

I've tried with

    def tupleRange[T <: Product](t1:T, t2:T):Seq[T] = {
        assert(t1.productArity == t2.productArity)
        def tail(t:Product):Product = sys.error("todo"); 
        def join(i:Int, p:Product):T = sys.error("todo");
        for(
v <- t1.productElement(0).asInstanceOf[Int] to t2.productElement(0).asInstanceOf[Int]; 
v2 <- tupleRange(tail(t1), tail(t2)))
            yield join(v,v2)
    }
    implicit def range[T <:Product](p1:T) = new { def to(p2:T) = tupleRange(p1,p2)}

But I think I've chosen wrong direction.

like image 700
yura Avatar asked Oct 03 '11 11:10

yura


1 Answers

I'd suggest the same thing that @ziggystar suggested above. Use List[Int] instead of tuples of Ints.

scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> def range(xs: List[Int], ys: List[Int]): List[List[Int]] = {
     |   (xs, ys).zipped.map((x, y) => List.range(x, y + 1)).sequence
     | }
range: (xs: List[Int], ys: List[Int])List[List[Int]]

scala> range(List(1, 2, 4), List(2, 5, 6))
res29: List[List[Int]] = List(List(1, 2, 4), List(1, 2, 5), List(1, 2, 6), 
List(1, 3, 4), List(1, 3, 5), List(1, 3, 6), List(1, 4, 4), List(1, 4, 5), 
List(1, 4, 6), List(1, 5, 4), List(1, 5, 5), List(1, 5, 6), List(2, 2, 4), 
List(2, 2, 5), List(2, 2, 6), List(2, 3, 4), List(2, 3, 5), List(2, 3, 6), 
List(2, 4, 4), List(2, 4, 5), List(2, 4, 6), List(2, 5, 4), List(2, 5, 5), 
List(2, 5, 6))

This implementation assumes that xs and ys are ordered and have same length.

like image 184
missingfaktor Avatar answered Sep 25 '22 15:09

missingfaktor