【问题标题】:Scala not infered typeScala 没有推断类型
【发布时间】:2018-12-17 21:55:08
【问题描述】:

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

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

【问题讨论】:

  • 尝试柯里化fn1,即将其定义为fn1(fn)(sorts),看看是否有帮助
  • 谢谢你,但遗憾的是它没有帮助

标签: scala slick


【解决方案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"))

据我所知,这两个版本都可以派生类型。

【讨论】:

  • 你说得对...我已经使用了这个{} 大括号,所以我得到了编译错误,但这样fn1(base1)((etq =&gt; etq._1.name, "name")) 它可以正常工作。很抱歉这个误导性的问题......现在我该怎么办?最好将您的答案标记为正确答案,否则我必须删除我的问题?
【解决方案2】:

我认为,这是因为函数是逆变的:_._1.name 可能是 (entity1Table, entity2Table) =&gt; String 或者可能是 Any =&gt; String,两者都满足类型约束,因为后者是前者的子类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2012-11-29
    相关资源
    最近更新 更多