tags:

views:

1161

answers:

3

I was just wondering, can I decompose a tuple type into its components' types in Scala?

I mean, something like this

trait Container {
  type Element
}

trait AssociativeContainer extends Container {
  type Element <: (Unit, Unit)
  def get(x : Element#First) : Element#Second
}
+2  A: 

You can't unpack, per se, but maybe this achieves what you want:

  type First
  type Second
  type Element = (First, Second)
  def get(x: First): Second
Jorge Ortiz
That's what I thought I needed to do, but wanted to avoid, because that would change the implementation of classes extending this trait.
jpalecek
Also, does this mean the Element pair would be the same Pair even in subclasses? Shouldn't it be rather Element <: (First, Second) [or maybe lower bounded, too]?
jpalecek
A: 

I'm a bit later to this, but what about using pattern matching? Doesn't have quite the correct return type, and my syntax might be a bit off, but here goes:

def get[K](key: K): Iterable[Any] {
  for ((key, x) <- elements) yield x
}
pdbartlett
+1  A: 

This doesn't unpack the types, but it does constrain the types A and B when calling get.

trait Container {
  type Element
}

trait AssociativeContainer extends Container {
  type Element <: Tuple2[_, _]

  def get[A, B](x: A)(implicit ev: (A, B) =:= Element): B
}

This looks promising, but is cheating -- it doesn't work if Element is abstract.

def Unpack[T<:Tuple2[_, _]] = new {
  def apply[A, B](implicit ev: T <:< (A, B)) = new {
    type AA = A
    type BB = B
  }
}

trait AssociativeContainer {
  type Element = (Int, String)
  val unpacked = Unpack[Element].apply
  type A = unpacked.AA
  type B = unpacked.BB

  1: A
  "": B
  def get(x: A): B
}
retronym