我有一个带有此签名的方法:
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自动推断类型?
答案 0 :(得分:1)
这是因为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 :(得分:0)
我认为,这是因为函数是互变的:_._1.name
可能是(entity1Table, entity2Table) => String
或可能是Any => String
,并且两者都将满足类型约束,因为后者是的子类。前者。