我有一个带有此签名的方法:
def fn1[A1, P, Q, E, U, C[_]](
fn: A1 => Query[E, U, C],
sorts: (E => Rep[_], String)*
)(implicit
aShape: Shape[ColumnsShapeLevel, A1, P, A1],
pShape: Shape[ColumnsShapeLevel, P, P, _]
) = ???
在我的课上,我有一个巧妙的查询定义为:
protected def base(id: Rep[Long]): Query[(entity1Table, entity2Table), (Entity1, Entity2), Seq] = ???
现在,我想做这样的事情:
fn1(base, (_._1.name, "name"))
或者,至少
fn1(base, (x => x._1.name, "name"))
但是,即使使用第二种方法,scala也无法推断x的类型,即(entity1Table, entity2Table)
,因此为了使其正确编译,我必须在编写时明确地告诉x的类型
fn1(base, ((x: (entity1Table, entity2Table)) => x._1.name, "name"))
为什么scala不能推断类型,我该怎么做才能让scala自动推断类型?
这是因为sorts
的类型参数源自first
参数fn
。但是,如果同时传递这两个函数,编译器对fn
一无所知,因此无法派生sorts
。
您需要curry
您的fn1
,这样编译器就可以首先处理fn
,然后使用派生类型来理解sorts
。
我对使用你的术语entity1Table
等有点困惑,所以我画了一个模拟模式来配合这个例子。
import slick.driver.H2Driver
import H2Driver.api._
case class Entity1(i: Int, s: String)
case class Entity2(i: Int, s: String)
class Entity1T(tag: Tag) extends Table[Entity1](tag, "Entity1s") {
def id = column[Int]("id", O.PrimaryKey) // This is the primary key column
def name = column[String]("name")
def * = (id, name) <> (Entity1.tupled, Entity1.unapply)
}
val entity1Table = TableQuery[Entity1T]
class Entity2T(tag: Tag) extends Table[Entity2](tag, "Entity2s") {
def id = column[Int]("id", O.PrimaryKey) // This is the primary key column
def name = column[String]("name")
def * = (id, name) <> (Entity2.tupled, Entity2.unapply)
}
val entity2Table = TableQuery[Entity2T]
现在,我不确定你想要哪一个,这个
def fn1[A1, P, Q, E, U, C[_]](
fn: A1 => Query[E, U, C]
)(
sort: (U => Rep[_], String)*
)(implicit
aShape: Shape[ColumnsShapeLevel, A1, P, A1],
pShape: Shape[ColumnsShapeLevel, P, P, _]
) = ???
protected def base1(id: Rep[Long]): Query[(TableQuery[Entity1T], TableQuery[Entity2T]), (Entity1T, Entity2T), Seq] = ???
val x1 = fn1(base1)((etq => etq._1.name, "name"))
或者这个,
def fn2[A1, P, Q, E, U, C[_]](
fn: A1 => Query[E, U, C]
)(
sort: (E => Rep[_], String)*
)(implicit
aShape: Shape[ColumnsShapeLevel, A1, P, A1],
pShape: Shape[ColumnsShapeLevel, P, P, _]
) = ???
protected def base2(id: Rep[Long]): Query[(Entity1T, Entity2T), (Entity1, Entity2), Seq] = ???
val x2 = fn1(base1)((etq => etq._1.name, "name"))
据我所见,这两个版本都能够派生类型。
我认为,这是因为函数是反变量的:_._1.name
可以是(entity1Table, entity2Table) => String
,也可以是Any => String
,两者都满足类型约束,因为后者是前者的子类。