I would have assumed that a type like e.g. Int *: Int *: EmptyTuple
is the same as (Int, Int)
both in theory and practice. However it seems that this is not so.
On a basic level they are interchangable:
scala> val a = (1, 2)
val a: (Int, Int) = (1,2)
scala> val b: (Int *: Int *: EmptyTuple) = a
val b: Int *: Int *: EmptyTuple = (1,2)
scala> val c: (Int, Int) = b
val c: (Int, Int) = (1,2)
scala> summon[(Int, Int) =:= (Int *: Int *: EmptyTuple)]
val res30: (Int, Int) =:= (Int, Int) = generalized constraint
However if we try to summon Mirror
instances for them, they do not behave the same:
scala> summon[Mirror.ProductOf[(Int, Int)]]
val res29: ( ...)
scala> summon[Mirror.ProductOf[Int *: Int *: EmptyTuple]]
-- Error:
1 |summon[Mirror.ProductOf[Int *: Int *: EmptyTuple]]
| ^
|no implicit argument of type deriving.Mirror.ProductOf[Int *: Int *: EmptyTuple] was found for parameter x of method summon in object Predef
So it seems that summoning a mirror for (Int, Int)
succeeds, while for Int *: Int * EmptyTuple
it fails. This is problematic since many operations on tuples return the latter version (even though it is shown as the former, just to add to the confusion):
scala> val x = (1, 2, 3)
val x: (Int, Int, Int) = (1,2,3)
scala> summon[Mirror.ProductOf[x.type]]
val res31: ( ...)
scala> val y = x.drop(1)
val y: (Int, Int) = (2,3)
scala> summon[Mirror.ProductOf[y.type]]
-- Error:
1 |summon[Mirror.ProductOf[y.type]]
| ^
|no implicit argument of type deriving.Mirror.ProductOf[(y : (Int, Int))] was found for parameter x of method summon in object Predef
Another example:
scala> val a = Tuple.fromProductTyped(1 *: 2 *: EmptyTuple)
-- Error:
1 |val a = Tuple.fromProductTyped(1 *: 2 *: EmptyTuple)
| ^
|no implicit argument of type deriving.Mirror.ProductOf[(Int, Int)] was found for parameter m of method fromProductTyped in object Tuple
scala> val b = Tuple.fromProductTyped((1, 2))
val b: (Int, Int) = (1,2)
scala> val c = Tuple.fromProductTyped(b)
-- Error:
1 |val c = Tuple.fromProductTyped(b)
| ^
|no implicit argument of type deriving.Mirror.ProductOf[(Int, Int)] was found for parameter m of method fromProductTyped in object Tuple
Is this behaviour intentional?