试图找出正确的类型

Attempting to figure out the correct type for this

抱歉,这将是一个有点菜鸟的问题。我有一个来自 slick 库的对象,它的类型如下:

Query[(Rep[String], Rep[String]), (String, String), Seq]

我正在尝试编写一个接受查询作为参数的函数,尽管其中的序列长度不确定 - 即,它同样可以是:

Query[(Rep[String], Rep[String], Rep[String]), (String, String, String), Seq]

因此前两个组件具有三个元素而不是两个。我不知道这是怎么做到的。我尝试了各种错误的排列,例如 Query[Product[Rep[String]], Product[String], Seq],但都无济于事,甚至我认为仅使用 Any 的核选项也不起作用。我的错误信息是

[error]  found   : Option[slick.driver.H2Driver.api.Query[(slick.driver.H2Driver.api.Rep[String], slick.driver.H2Driver.api.Rep[String]),(String, St
ring),Seq]]
[error]     (which expands to)  Option[slick.lifted.Query[(slick.lifted.Rep[String], slick.lifted.Rep[String]),(String, String),Seq]]
[error]  required: Option[slick.driver.H2Driver.api.Rep[scala.concurrent.Future[List[String]]]]
[error]     (which expands to)  Option[slick.lifted.Rep[scala.concurrent.Future[List[String]]]]
[error]       ReturnFunctions.completeQuery(db, query, serialize_and_send)

我认为我无法解决这个问题可能反映出对 scala、一般强类型语言以及可能对整个计算缺乏基本的理解。在尝试将其传递给函数之前,我是否应该将此查询解析为更明确的形式?我还怀疑我没有正确解释原始类型——括号在这种情况下是什么意思? Query 是否期望接收三组参数,一个接一个,就像你执行 fn(arg1)(arg2)(arg3) = ...?

非常感谢任何解决这个令人不安的困境的帮助。

I also suspect I'm not interpreting the original type correctly - what do the parentheses mean in this context?

您看到的是一个合理的高级区域,但让我们尝试提供帮助。

Query 类型始终具有三个类型参数。您会看到它们写成 Query[M, U, C]

第一个参数,M,是一个元组。这就是括号在这种情况下的意思。

在您的第一个示例中,M 是两个元素的元组;第二个是三个。第二个参数 U 也存在同样的情况。 Essential Slick.

中有更多详细信息

在 Scala 中,您可以使用泛型参数。这意味着您可以按照以下方式说一些话:

def foo[M, U, C[_]](q: Query[M,U,C]) = ???

我们定义了一个方法:

  • 三个类型参数;和
  • 采用具有这些类型的查询参数。

我们没有说任何关于 MU 的事情,也没有说太多关于 C 的事情(除了它是一个以类型作为参数的类型)。这意味着我们对它们无能为力,但您可能不需要。

query enrichment in Slick 上的 post 给出了一个可能有用的更长(相关)示例。

正如 Dmytro 所建议的,更好的方法是创建一个具体示例,说明您希望实现的目标并以此为基础开展工作。

考虑Query类型构造函数的形状

Query[+E, U, C[_]]

我们说 Query 是类型 constructor 因为它根据给定的类型参数 EUU 构造了一个具体类型C[_],类似于函数如何根据给定的函数参数构造具体值。

现在让我们尝试解构具体类型

Query[(Rep[String], Rep[String]), (String, String), Seq]

进入其组成类型参数。我们有

E     = (Rep[String], Rep[String])
U     = (String, String)
C[_]  = Seq

注意 (A, B) 只是 Tuple2[A, B] 的语法糖,因此

E     = (Rep[String], Rep[String]) = Tuple2[Rep[String], Rep[String]]
U     = (String, String)           = Tuple2[String, String]
C[_]  = Seq                        = Seq

您可能想知道 C[_] 中的下划线。这指定类型参数 C 必须是类型构造函数而不是具体类型。例如 Seq 是类型构造函数,而 Seq[Int] 不是。此外,您可能想知道 +E 中的 +。这指定了参数化类型的继承关系,或者说变体,例如,它指定Seq[Dog]是否是Seq[Animal]的子类型。

最后让我们详细地写出最终的具体类型

Query[Tuple2[Rep[String], Rep[String]], Tuple2[String, String], Seq]