Scala推断类型参数-推断为';没有';

Scala推断类型参数-推断为';没有';,scala,generics,type-inference,type-bounds,Scala,Generics,Type Inference,Type Bounds,我正试图编写一个简单的查询monad,但在获取正确的泛型类型注释时遇到了困难 我的第一次尝试如下(为简洁起见大大简化) 案例类人员(val名称:字符串) 抽象类模式[T] 对象人扩展模式[人] case class Query[U我总是发现,当在一个类/函数上使用两个类型标识符时,类型推断系统不能像预期的那样工作,您必须像这样显式: val query = Query[People.type, Person]( People ) 如果您将查询声明更改为: case class Query[

我正试图编写一个简单的查询monad,但在获取正确的泛型类型注释时遇到了困难

我的第一次尝试如下(为简洁起见大大简化)

案例类人员(val名称:字符串)
抽象类模式[T]
对象人扩展模式[人]

case class Query[U我总是发现,当在一个类/函数上使用两个类型标识符时,类型推断系统不能像预期的那样工作,您必须像这样显式:

val query = Query[People.type, Person]( People )  
如果您将
查询
声明更改为:

case class Query[U <: Schema[_]( schema: U )

但是,您将不知道所提供的
模式的基本类型,也无法正确实现
结果
功能。

这不是一个完全统计的答案(至少对我来说)我不得不承认,我不能确切地说出推理失败的地方和原因。我对它只有一些模糊的直觉。 这个问题与编译器必须一次推断两个类型参数有关。 至于为什么将类型绑定更改为视图绑定会修复编译,我的理解是现在有两个参数列表,因此我们现在有两个连续的类型推断阶段,而不是 一次两个推论。事实上,如下:

case class Query[U <% Schema[T], T]( schema: U )
第一个参数列表驱动
U
的推断,然后第二个参数列表(注意
U
现在已知)将驱动
T
的推断

对于表达式
Query(People)
,参数
People
将驱动类型推断器将
U
设置为
People.type
。然后,编译器将查找从
People.type
Schema[T]的隐式转换
,以传递第二个参数列表。范围中唯一的一个参数是从
人。键入
模式[人]
,驱动推理器推断出
T=Person

要修复编译而不诉诸视图绑定,可以将类型参数
T
替换为抽象类型:

case class Person( val name: String )
sealed trait Schema {
  type T
}
abstract class SchemaImpl[_T] extends Schema {
  type T = _T
}
object People extends SchemaImpl[Person]
case class Query[U <: Schema]( schema: U ) {
  def results: Seq[schema.T] = ???
}
class TypeText extends Application {
  val query = Query( People )
}
甚至不编译。 假设你的意思是

case class Query[U <: Schema[_], T](schema: U)

case class Query[U为了对两个类型参数之间的关系进行编码,可以使用

case class Query[U, T](schema: U)(implicit ev: U <:< Schema[T]) { ... }

case-class-Query[U,T](schema:U)(隐式ev:U

case class Query[U <: Schema[T], T]( schema: U with Schema[T] ) {
    ...
}

case class Query[U谢谢。我已经看到了这个语法,并且想知道它是什么意思。我认为这个答案不正确。请检查我在答案底部的回复(这个评论不会为讨论提供足够的空间)@Régis你是对的。我误解了规范中的范围规则。正如你在回答中所述,这确实是一个推理问题。也就是说,使用隐式证据参数是编码关系和支持所需推理的最简单方法。
case class Person( val name: String )
sealed trait Schema {
  type T
}
abstract class SchemaImpl[_T] extends Schema {
  type T = _T
}
object People extends SchemaImpl[Person]
case class Query[U <: Schema]( schema: U ) {
  def results: Seq[schema.T] = ???
}
class TypeText extends Application {
  val query = Query( People )
}
case class Query[U <: Schema[X], T](schema: U)
case class Query[U <: Schema[_], T](schema: U)
case class Query[U <: Schema[_], T](schema: U)
type MyQuery = Query[Schema[String], Int]
case class Query[U <: Schema[T], T](schema: U)
type MyQuery = Query[Schema[String], Int]
<console>:10: error: type arguments [Schema[String],Int] do not conform to class Query's type parameter bounds [U <: Schema[T],T]
       type MyQuery = Query[Schema[String], Int]
case class Query[U, T](schema: U)(implicit ev: U <:< Schema[T]) { ... }
case class Query[U <: Schema[T], T]( schema: U with Schema[T] ) {
    ...
}