I am attempting to generate an API in Scala 3 that concatenates Iterable
of Tuple
. Say I have the following functions that zip these Iterable
def and[A,B](a1: Iterable[A], a2: Iterable[B])
(implicit d: DummyImplicit): Iterable[(A,B)] =
a1.zip(a2)
def and[A<:Tuple,B<:Tuple](a1: Iterable[A], a2: Iterable[B])
(implicit d1: DummyImplicit, d2: DummyImplicit):
Iterable[Tuple.Concat[A,B]] =
a1.zip(a2).map( (a,b) => a ++ b)
No I can do this:
val s1 = 1 to 3 by 1
val s2 = 1 to 6 by 2
val s3 = 'a' to 'f'
val r1: Iterable[(Int, Int)] = and(s1,s2)
println(r1)
val r2: Iterable[(Int, Int, Int, Int)] = and(r1, r1)
println(r2)
However, this won’t compile:
val r4: Iterable[(Char, Int, Int)] = and( s3, r1)
println(r4)
generating this error:
error] 510 | val r4: Iterable[(Char, Int, Int)] = and( s3, r1)
[error] | ^^^^^^^^^^^^
[error] | Found: Iterable[(Char, (Int, Int))]
[error] | Required: Iterable[(Char, Int, Int)]
[error] one error found
The problem here is that I would like the user not be require to convert a single non-tuple element to any Tuple1
. So I added this function:
def and[A,B<:Tuple](a1: Iterable[A], a2: Iterable[B])
(implicit d1: DummyImplicit,
d2: DummyImplicit,
d3: DummyImplicit):
Iterable[*:[A,B]] =
a1.zip(a2).map( (a,b) => a *: b)
Note that I am using dummy implicits to “circumvent” the double definition as discusses here.
The above will also not allow compilation, because now the type A
can successfully match a single element or a tuple. I then tried avoiding such as much using the following code:
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
// This pair excludes the A =:= B case
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null
def and[A,B<:Tuple](a1: Iterable[A], a2: Iterable[B])
(implicit d1: DummyImplicit,
d2: DummyImplicit,
d3: DummyImplicit,
ev: A =!= Tuple): Iterable[*:[A,B]] =
a1.zip(a2).map( (a,b) => a *: b)
and that still fails with
error] 507 | val r2: Iterable[(Int, Int, Int, Int)] = and(r1, r1)
[error] | ^^
[error] | Found: (r1 : Iterable[(Int, Int)])
[error] | Required: Iterable[Int]
[error] -- [E007] Type Mismatch Error: /home/hmf/IdeaProjects/pdm_toyadmos/dcase2020/test/src/data/synthetic/TimeSeriesSpec.scala:507:53
[error] 507 | val r2: Iterable[(Int, Int, Int, Int)] = and(r1, r1)
[error] | ^^
[error] | Found: (r1 : Iterable[(Int, Int)])
[error] | Required: Iterable[(Int, Int, Int)]
[error] two errors found
So my question is, is this doable and if so how?
TIA,
HF