Scala不是推理类型



我有一个带有此签名的方法:

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,两者都满足类型约束,因为后者是前者的子类。

最新更新