Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala [F<;:List[A],A]和[F[3;]<;:List[A],A]之间的推理差异_Scala_Type Inference_Scala 3_Type Constructor - Fatal编程技术网

Scala [F<;:List[A],A]和[F[3;]<;:List[A],A]之间的推理差异

Scala [F<;:List[A],A]和[F[3;]<;:List[A],A]之间的推理差异,scala,type-inference,scala-3,type-constructor,Scala,Type Inference,Scala 3,Type Constructor,在下面两个类型参数子句中,考虑类型参数A对类型构造函数的推断的差异 $ scala3-repl scala> def f[F <: List[A], A](as: F) = as def f[F <: List[A], A](as: F): F scala> f(List(42)) val res0: List[Int] = List(42) scala> def f[F[_] <: List[A], A](as: F[A]) = as def f[F[_

在下面两个类型参数子句中,考虑类型参数
A
对类型构造函数的推断的差异

$ scala3-repl
scala> def f[F <: List[A], A](as: F) = as
def f[F <: List[A], A](as: F): F

scala> f(List(42))
val res0: List[Int] = List(42)

scala> def f[F[_] <: List[A], A](as: F[A]) = as
def f[F[_$1] <: List[A], A](as: F[A]): F[A]

scala> f(List(42))
val res1: List[Any] = List(42)
$scala3 repl

scala>def[f def f[f[\u]根据我对您在第二种情况下的定义的解释,
f[\u]
是一个
List
类型构造函数,但是
List[a]
必须是任何List
f[\u]
可以构造的上限,因此
a
必须是
any

可能你想要的是:


def[f[\p>不是一个完整的答案,只是一些值得思考的东西:我试图构建一个反例,但在假设
a
将被推断为最狭义的类型的情况下,无法想出任何实际会导致不合理的东西。不过,也许你会觉得有趣

这里是一个具有类似约束的函数
h
,但我们采用的是稍微不同的类型构造函数,而不是
List

其主要思想是,
Cc
有两个独立的类型参数:

  • 第一个是在
    F[\u]
  • 第二个是与
    trait Lst[+X]中的
    A
    交互的 //定义性状 scala>case类Cc[+I,+X](I:I)扩展了Lst[X] //已定义案例类别Cc scala>类型T[+I]=Cc[I,无] //定义的别名类型T[+I]=Cc[I,无] scala>def h[F[]h(xs) val res9:Cc[Int,Nothing]=Cc(42)

    如果
    A
    被推断为满足
    约束的最窄可能类型,那么为什么在第一种情况下当约束看起来相同时会推断Int?有什么区别?@MarioGalic我已经更新了答案以涵盖第一种情况。不知道是否足够清楚。在这两种情况下,最窄可能类型已经是infrred。@用户我认为两者都应该起作用。我不知道是否有区别。如果您发现一个只适用于1种情况的示例,可以让我知道。我认为这两种方法都适用于这种情况,但如果您想对
    as
    执行操作,则需要使用下划线和通配符以外的内容。也就是说,
    F[x]@user我将添加这一点作为替代,然后这就是Scala编译器如何处理没有类型绑定的通配符类型参数。它将只推断为
    Any
    。如果有类型绑定,它将类似于
    $1,其中xxxx@texasbruce在第一种情况下也没有类型绑定参数?在第一种情况下,F不是类型constr构造函数,但它是一个完整类型,是列表[a]的子类型。当您传递列表[Int]时,F在编译器中注册为列表[Int]。在类型构造函数的第二种情况下,编译器只注意到F是一个类型构造函数,它接受任何值(因为您传递了一个通配符)和列表[a](推断为列表[Int])更具体地说,您正试图将F[A](自动推断)返回为List[Int],因此A必须是Any。(在Scala2中失败)。在@yangai的回答中,F和List都使用Any,因此它也可以工作。@MarioGalic在第二种情况下,如果您显式地使
    A
    an
    Int
    类似于
    F[List,Int](List(42))
    它不会编译。总之,在这两种情况下,推断的类型已经是可能的最窄类型。@texasbruce在第一种情况下,编译器能够解构正确的类型
    列表[Int]
    A
    选择
    Int
    ,这在Scala 2中并非如此,因此它似乎比简单地将
    List[Int]
    分配给
    F
    更为重要。
    (run in 3.0.0-RC2)
    
    scala> trait Lst[+X]
    // defined trait Lst
    
    scala> case class Cc[+I, +X](i: I) extends Lst[X]
    // defined case class Cc
    
    scala> type T[+I] = Cc[I, Nothing]
    // defined alias type T[+I] = Cc[I, Nothing]
    
    scala> def h[F[_] <: Lst[A], A](as: F[A]) = as
    def h[F[_$1] <: Lst[A], A](as: F[A]): F[A]
    
    scala> val xs: T[Int] = Cc(42)
    val xs: T[Int] = Cc(42)
    
    scala> h(xs)                                                                                             
    val res9: Cc[Int, Nothing] = Cc(42)