为什么 A => String 与 _1.type => String where val _1: A 不同?
Why is A => String not the same as _1.type => String where val _1: A?
在此 Scala 2.13 示例中:
import scala.language.implicitConversions
object Main2 extends App {
trait Foo {
type F = this.type => String
}
def fooA[A <: Foo](f: A#F, toString: A#F => String): String = toString(f)
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
}
它失败了:
type mismatch;
found : _1.type => String where val _1: A
required: A => String
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
为什么 A => String
和 _1.type => String where val _1: A
不一样?
投f.asInstanceOf[(A => String)]
安全吗?
是否有一个具体的例子表明这不起作用?
一个不起作用的具体例子:
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = ???
trait X extends Foo
trait Y extends Foo
def ok(f: X#F, toString: (Y => String) => String) = fooB(f, toString)
这会编译,因为编译器将类型参数 A
解析为 Foo
。但是 f
显然不是 toString
的有效参数。
我想你误解了什么是this.type
。来自 scala 2.13 spec:
Every value in Scala has a type which is of one of the following forms.
A singleton type is of the form
p
.
p.type. Where
p
p is a path pointing to a value which conforms to scala.AnyRef, the type denotes the set of values consisting of null and the value denoted by
p
p (i.e., the value
v
v for which v eq p)
这意味着 this.type
对于 Foo
的每个实例都是唯一的。在 fooB
:
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
编译器发现您试图传递 f
类型是:
(some object of A which upper-bouned by Foo).type => String
function from singleton-type object
to String
into function 什么函数从 A
类型的对象到 String
.
注意类型A
(new A()
)的对象与(new A()).type
的类型不同,它们有不同的类型,这是编译器显示错误的原因。
例如,你可以写类似的东西,它会编译:
class Bar extends Foo {
def conversion: this.type => String = b => "bar"
}
def someStringConversion[A <: Foo]: A#F => String = ???
val bar: Bar = new Bar
someStringConversion[Bar](bar.conversion)
val conversionType: bar.type => String = bar.conversion
val customConversion: bar.type => String = (x: bar.type) => "some string"
someStringConversion[Bar](customConversion)
因为 bar.type
与 this.type
具有相同的类型(它们都指的是一种单例类型 - bar.type
结论
你的函数 fooA
和 fooB
有不同的签名,A#F => String
和 A => String
不一样,你不能先用 asInstanceOf
. fooB
不适用于 Foo
的任何实例,因为任何 Foo
实例都有自己的 this.type
单例类型。它与 Foo
无关,而某些 Foo
实现与 Foo
.
相关
在此 Scala 2.13 示例中:
import scala.language.implicitConversions
object Main2 extends App {
trait Foo {
type F = this.type => String
}
def fooA[A <: Foo](f: A#F, toString: A#F => String): String = toString(f)
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
}
它失败了:
type mismatch;
found : _1.type => String where val _1: A
required: A => String
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
为什么 A => String
和 _1.type => String where val _1: A
不一样?
投f.asInstanceOf[(A => String)]
安全吗?
是否有一个具体的例子表明这不起作用?
一个不起作用的具体例子:
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = ???
trait X extends Foo
trait Y extends Foo
def ok(f: X#F, toString: (Y => String) => String) = fooB(f, toString)
这会编译,因为编译器将类型参数 A
解析为 Foo
。但是 f
显然不是 toString
的有效参数。
我想你误解了什么是this.type
。来自 scala 2.13 spec:
Every value in Scala has a type which is of one of the following forms. A singleton type is of the form p . p.type. Where p p is a path pointing to a value which conforms to scala.AnyRef, the type denotes the set of values consisting of null and the value denoted by p p (i.e., the value v v for which v eq p)
这意味着 this.type
对于 Foo
的每个实例都是唯一的。在 fooB
:
def fooB[A <: Foo](f: A#F, toString: (A => String) => String): String = toString(f)
编译器发现您试图传递 f
类型是:
(some object of A which upper-bouned by Foo).type => String
function from singleton-type object
to String
into function 什么函数从 A
类型的对象到 String
.
注意类型A
(new A()
)的对象与(new A()).type
的类型不同,它们有不同的类型,这是编译器显示错误的原因。
例如,你可以写类似的东西,它会编译:
class Bar extends Foo {
def conversion: this.type => String = b => "bar"
}
def someStringConversion[A <: Foo]: A#F => String = ???
val bar: Bar = new Bar
someStringConversion[Bar](bar.conversion)
val conversionType: bar.type => String = bar.conversion
val customConversion: bar.type => String = (x: bar.type) => "some string"
someStringConversion[Bar](customConversion)
因为 bar.type
与 this.type
具有相同的类型(它们都指的是一种单例类型 - bar.type
结论
你的函数 fooA
和 fooB
有不同的签名,A#F => String
和 A => String
不一样,你不能先用 asInstanceOf
. fooB
不适用于 Foo
的任何实例,因为任何 Foo
实例都有自己的 this.type
单例类型。它与 Foo
无关,而某些 Foo
实现与 Foo
.