Скала не выведена типа - PullRequest
       8

Скала не выведена типа

0 голосов
/ 17 декабря 2018

У меня есть метод с такой подписью:

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 голосов
/ 17 декабря 2018

Это потому, что параметры типа вашего 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"))

Из того, что я вижу, обе версии могут получать типы.

0 голосов
/ 17 декабря 2018

Я думаю, это потому, что функции контравариантны: _._1.name может быть (entity1Table, entity2Table) => String или Any => String, и либо будет удовлетворять ограничению типа, поскольку последний является подклассом первого.

...