Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala tuple type composition

Tags:

types

scala

Given a Tuple type

type T = (String, Int, String)

Is there any way I can get a type T1, where T1 would be

type T1 = (MyClass, String, Int, String)

I would love to be able to declare a class like

class TupleTypes[T] extends AnotherClass[T1]

Note: The tuple size is not known and

type T1 = (MyClass, T)

will not return what I want, it will return (MyClass, (String, Int, String)) which is different.

Thanks

like image 633
mericano1 Avatar asked Mar 30 '12 17:03

mericano1


3 Answers

You can do this using the HList to tuple conversions from shapeless.

scala> import shapeless._ ; import Tuples._
import shapeless._
import Tuples._

scala> class MyClass ; val m = new MyClass
defined class MyClass
m: MyClass = MyClass@3859023a

scala> val t1 = ("foo", 23, "bar")
t1: (String, Int, String) = (foo,23,bar)

scala> val t2 = (m :: t1.hlisted) tupled
t2: (MyClass, String, Int, String) = (MyClass@3859023a,foo,23,bar)
like image 168
Miles Sabin Avatar answered Oct 30 '22 20:10

Miles Sabin


In my opinion there are no such constructs for tuples, but HList have a behavior very similar to the one you showed. They are considered has advanced type programming structure, and usage can be difficult depending on what you want to achieve. Here are an excellent starter and a nice implementation.

like image 33
paradigmatic Avatar answered Oct 30 '22 22:10

paradigmatic


late to the party, but in the event that you are seeking a "better" solution in regard to the ScalaQuery problem, try this:

1) create mapper base class with ID

import org.scalaquery.ql.extended.{ExtendedTable => Table}

abstract class Mapper[T](table: String) extends Table[T](None, table) {
  def id = column[Int]("id", O PrimaryKey)
}

2) extend mapper base using case class/companion object (i.e. not tuple based)

case class Foo (bar: String)
object Foos extends _Mapper[Foo]("foo") {
  def foo = column[String]("foo")
}

then you can do something like:

def show: List[Foo] = {
  val q = (for { f <- Foos } yield f)

  val foos = db withSession {
    foos.list map { case t:T => t }
  }
  render(foos)
}

and have a navigable object to work with (vs. index-based tuple).

Now, sometimes you don't want an enormous object graph when you only need a subset of fields from a group of entities.

That's where projections come in, just create a case class that represents the set of fields that you want and, voila, a navigable projection object to work with:

case class Yum (foo: String, baz: String)

def show: List[Yum] = {
  val q = (for { f <- Foos; b <- Bars; if f.id is b.fooID } yield (f.foo, b.baz))

  val yums = db withSession {
    yums.list map { case t:T => t }
  }
  render(yums)
}

Fairly simple, should be encapsulated in a cake driven DAO, but the general principle is: take the case class/object route.

Should note that ScalaQuery kicks unbelievable azz, Zeiger is brilliant! (as are many in the Scala community, future is looking bright on Scala way ;-))

like image 33
virtualeyes Avatar answered Oct 30 '22 22:10

virtualeyes