Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.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 为什么传递Int时预期F[1;]参数有效?_Scala_Higher Kinded Types - Fatal编程技术网

Scala 为什么传递Int时预期F[1;]参数有效?

Scala 为什么传递Int时预期F[1;]参数有效?,scala,higher-kinded-types,Scala,Higher Kinded Types,假设我们有一个函数: def bar[F[_], A](x: F[A], y: F[A]) = null 以下所有行为都是明确的: bar(List(1, 2, 3), List(1)) // compiles ok bar(List(1), Some(1)) // doesn't compile 但是, 为什么? 另外,我认为您遇到了类型推断系统的局限性。为了阐明这一点,让我们看看当我们重新定义它以获得更有用的输出时会发生什么: class Bar[F[_], A](x: F[A], y:

假设我们有一个函数:

def bar[F[_], A](x: F[A], y: F[A]) = null
以下所有行为都是明确的:

bar(List(1, 2, 3), List(1)) // compiles ok
bar(List(1), Some(1)) // doesn't compile
但是,

为什么?


另外,我认为您遇到了类型推断系统的局限性。为了阐明这一点,让我们看看当我们重新定义它以获得更有用的输出时会发生什么:

class Bar[F[_], A](x: F[A], y: F[A]) {}
res0: Bar[List,Int] = Bar@69f1a286
new Bar(List(1,2,3), List(1))
res1: Bar[Any,Int] = Bar@7b139eab
new Bar(List(1), 1)
res2: Bar[Any,Int] = Bar@456be73c
new Bar(List(1), Some(1))
<console>:12: error: inferred kinds of the type arguments (Product with java.io.Serializable,Int) do not conform to the expected kinds of the type parameters (type F,type A) in class Bar.
Product with java.io.Serializable's type parameters do not match type F's expected parameters:
<refinement of Product with java.io.Serializable> has no type parameters, but type F has one
       new Bar(List(1), Some(1))
       ^
<console>:12: error: type mismatch;
 found   : List[Int]
 required: F[A]
       new Bar(List(1), Some(1))
                   ^
<console>:12: error: type mismatch;
 found   : Some[Int]
 required: F[A]
       new Bar(List(1), Some(1))

对我来说,这表明类型推断系统无法正确推断类型,或者它推断的类型不正确。

这是有效的,因为编译器为您推断了一些类型。下面是添加到
栏中的类型的外观:

  bar[Any, Int](1, List(1)) // compile ok
  bar[Any, Nothing](1, 1) // compile ok

这不适用于
bar(List(1),Some(1))
,因为编译器无法推断出同时支持
List
Some
的类型。不过,您可以像上面那样对其进行降级,
bar[Any,Int](List(1),Some(1))
有效。

我认为下面给出了一个线索(尽管仍有一些谜团):

def baz[F[uz],A](x:F[A]):F[A]=x
scala>baz(“str”)
res5:可比较的[String]=str
scala>baz(1)
res6:Any=1
scala>class-Foo
定义类Foo
scala>baz(新食品)
:15:错误:不存在方法baz:(x:F[A])F[A]的类型参数,因此无法将其应用于参数(Foo)
---因为---
参数表达式的类型与形式参数类型不兼容;
发现:富
所需:?F
巴兹(新富)
^
:15:错误:类型不匹配;
发现:富
所需:F[A]
巴兹(新富)
^
scala>案例类Foo2
警告:有1个弃用警告;有关详细信息,请使用-deprecation重新运行
定义类Foo2
scala>baz(Foo2)
res10:scala.runtime.AbstractFunction0[Foo2]=Foo2
因此,函数
bar
baz
可以查找任何容器类型(
compariable
用于字符串,
AbstractFunction0
用于案例类等),以匹配预期的
F[\u]


推测:在
Int
的情况下,我怀疑我们针对底层字节码中的(装箱的)基元类型使用了一种特殊的“容器”类型。如果这种特殊类型只能作为“
Any
”打印回Scala,但实际上是某种特殊类型,我们可以将其视为“
Any[\u]
”,那么这可以解释我们看到的结果。为了证实这与原语的特殊处理有关,请注意,对于非原语简单类型,如上面的(非case)类
Foo

似乎与
Any
类型结合在一起时会出现一些问题

Any
不接受类型参数:
vali:Any[Int]=1
给出一个错误,因此它应该是简单类型的

Any
可用于需要更高种类类型的位置,如您在示例
bar[Any,Nothing](1,1)

如果我们在更高级的位置使用
Any
,这个类型参数会神奇地变成一个简单的类型,而前一个高级类型的类型参数会被完全忽略

bar
的第一个类型参数为
Any
时,我们可以将任何类型作为第二个参数,并且它将始终编译:

bar[Any,String](List(1),List(2))
bar[Any, Boolean](1,2)
bar[Any, Int](List(), true)
case class A()
bar[Any, A](List, A)
类型推断似乎存在问题,导致一些示例在没有类型注释的情况下失败


我已经通过反复试验发现了这种行为,我不知道它是bug还是特性;-)

Any
Nothing
都是多态的,例如,顺便说一句
bar(1,列表(1))
不在
2.9
中编译,但在
2.10
中编译。
  bar[Any, Int](1, List(1)) // compile ok
  bar[Any, Nothing](1, 1) // compile ok
def baz[F[_], A](x: F[A]): F[A] = x

scala> baz("str")
res5: Comparable[String] = str

scala> baz(1)
res6: Any = 1

scala> class Foo
defined class Foo

scala> baz(new Foo)
<console>:15: error: no type parameters for method baz: (x: F[A])F[A] exist so that it can be applied to arguments (Foo)
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : Foo
 required: ?F
              baz(new Foo)
              ^
<console>:15: error: type mismatch;
 found   : Foo
 required: F[A]
              baz(new Foo)
                  ^

scala> case class Foo2
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
defined class Foo2

scala> baz(Foo2)
res10: scala.runtime.AbstractFunction0[Foo2] = Foo2
bar[Any,String](List(1),List(2))
bar[Any, Boolean](1,2)
bar[Any, Int](List(), true)
case class A()
bar[Any, A](List, A)