Scala无法推断类型

时间:2018-12-17 10:27:08

标签: scala slick

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

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自动推断类型?

2 个答案:

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