У меня есть метод с такой подписью:
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 автоматически определяла тип?
спасибо, но, к сожалению, это не помогает
Я думаю, это потому, что функции контравариантны: _._1.name
может быть (entity1Table, entity2Table) => String
или Any => String
, и любой из них удовлетворяет ограничению типа, потому что последний является подклассом первого.
Это связано с тем, что параметры типа вашего 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 => etq._1.name, "name"))
работает правильно. Извините за вводящий в заблуждение вопрос ... Что мне теперь делать? Лучше отметить свой ответ как правильный o Мне нужно удалить свой вопрос?
попробуйте каррировать
fn1
, т.е. определите его какfn1(fn)(sorts)
, чтобы узнать, поможет ли это