gpt4 book ai didi

Scala 推断类型参数 - 推断为 'Nothing' 的类型边界

转载 作者:行者123 更新时间:2023-12-04 11:08:38 24 4
gpt4 key购买 nike

我正在尝试编写一个简单的查询单子(monad),但无法正确获取我的泛型类型注释。

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

case class Person( val name: String )
abstract class Schema[T]
object People extends Schema[Person]

case class Query[U <: Schema[T], T]( schema: U ) { <---- Type signature
def results: Seq[T] = ...
def where( f: U => Operation ) = ...
}

class TypeText extends Application {
val query = Query( People ) <---- Type inference fails
}

编译器不喜欢这样,因为它无法推断“T”的类型。

error: inferred type arguments [People.type,Nothing] do not conform to method apply's type parameter bounds [U <: Schema[T],T]



在试验时,我发现使用 View 边界可以按预期工作
case class Query[U <% Schema[T], T]( schema: U ) {

(注意使用 View 绑定(bind)“<%”而不是类型绑定(bind)“<:”)

然而,在我对类型系统的有限理解中,由于我期待 Schema[T] 的实际子类(而不仅仅是可转换性),我会假设类型绑定(bind)“<:”是在这里使用的正确边界?

如果是这种情况,我错过了什么 - 如何在使用类型边界而不是 View 边界时为编译器提供足够的提示以正确推断 T?

最佳答案

这不是一个完全令人满意的答案(至少对我而言),因为我不得不承认我无法准确说明推理在哪里以及为什么在这里失败。我对此只有一些模糊的直觉。
该问题与编译器必须一次推断两个类型参数有关。
至于为什么更改绑定(bind)到 View 绑定(bind)的类型可以修复编译,我的理解是现在有两个参数列表,因此我们现在有两个连续的类型推断阶段,而不是
一次推论两个。确实,以下内容:

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

是相同的:
case class Query[U, T]( schema: U )( implicit conv: U => Schema[T] )

第一个参数列表驱动 U 的推断,然后第二个(注意 U 现在已知)将驱动 T 的推断.

在表达式 Query( People ) 的情况下,参数 People将驱动类型推断器设置 UPeople.type .然后,编译器将从 People.type 中查找隐式转换。至 Schema[T] , 传入第二个参数列表。范围内的唯一一个是来自 People.type 的(微不足道的)转换。至 Schema[Person] ,驱动推理器推断出 T = Person .

要在不使用 View 绑定(bind)的情况下修复编译,可以替换类型参数 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 )
}

更新 :

@Aaron Novstrup 的:
据我所知,您的答案不正确(更新更新:Aaron 的原始答案声称 Query 声明等同于 case class Query[U <: Schema[X], T](schema: U) )。
case class Query[U <: Schema[X], T](schema: U)

甚至不编译。
假设你的意思是
case class Query[U <: Schema[_], T](schema: U)

( 确实 编译),很容易在 REPL 中检查它也不相同。

确实,以下编译得很好:
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]

这清楚地表明 T 的第一次和第二次出现表示同一类型,我们 两个类型参数之间有关系。

关于Scala 推断类型参数 - 推断为 'Nothing' 的类型边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16291313/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com