函数定义中返回类型后的大括号 [英] Curly Parentheses After Return Type in Function Definition
问题描述
阅读 cats 库时函子源码,没看懂toFunctorOps函数返回类型后面的curl块是干什么的;我的猜测是这个块将作为构造函数的一部分执行?如果是这样,那么为什么类型 TypeClassType 用相同的代码定义了两次 type TypeClassType = Functor[F]?
When read the cats library's Functor source, I could not understand what the curly block after the return type of the function toFunctorOps does; My guess is that this block will be executed as part of constructor? If so, then why type TypeClassType is defined twice with the same code type TypeClassType = Functor[F]?
trait Ops[F[_], A] extends Serializable {
type TypeClassType <: Functor[F]
def self: F[A]
val typeClassInstance: TypeClassType
def map[B](f: A => B): F[B] = typeClassInstance.map[A, B](self)(f)
...
}
trait ToFunctorOps extends Serializable {
implicit def toFunctorOps[F[_], A](target: F[A])(implicit tc: Functor[F]): Ops[F, A] {
type TypeClassType = Functor[F]
} =
new Ops[F, A] {
type TypeClassType = Functor[F]
val self: F[A] = target
val typeClassInstance: TypeClassType = tc
}
}
推荐答案
我不明白返回类型后面的卷曲块是什么......
I could not understand what the curly block after the return type ... does
细化{ type TypeClassType = Functor[F] }
进一步限制了特征Ops
的类型成员TypeClassType
.换句话说,它向编译器提供了关于方法 toFunctorOps
The refinement { type TypeClassType = Functor[F] }
puts a further constraint on type member TypeClassType
of trait Ops
. In other words it gives more information to the compiler about the specific return type of method toFunctorOps
Ops[F, A] { type TypeClassType = Functor[F] }
注意细化块被认为是返回类型的部分,与构造函数无关.
Note the refinement block is considered part of the return type and has nothing to do with the constructor.
让我们简化类型以更好地说明概念,所以考虑
Let us simplify the types to illustrate the concept better, so consider
trait Foo {
type A
def bar: A
}
val foo: Foo = new Foo {
type A = Int
def bar: A = ???
}
val x: foo.A = 42 // type mismatch error
注意变量 foo
的静态类型如何不包括类型成员 A
已实例化为 Int
的特定信息.现在让我们使用类型细化向编译器提供这些信息
Note how static type of variable foo
does not include specific information that type member A
has been instantiated to Int
. Now let's give the compiler this information by using type refinement
val foo: Foo { type A = Int } = new Foo {
type A = Int
def bar: A = ???
}
val x: foo.A = 42 // ok
现在编译器知道类型成员 A
正是一个 Int
.
Now compiler knows that type member A
is precisely an Int
.
类型类的设计者在何时使用类型成员而不是类型参数方面做出明智的决定,有时甚至在您的情况下两者混合使用.例如特征 Foo
可以像这样被参数化
Designers of type classes make judicious decisions regarding when to use type members as opposed to type parameters, and sometimes there is even a mix of the two as in your case. For example trait Foo
could have been parameterised like so
trait Foo[A] {
def bar: A
}
val foo: Foo[Int] = new Foo[Int] {
def bar: Int = ???
}
并且编译器将再次获得类型参数 A
已实例化为 Int
的精确信息.
and compiler would again have precise information that type parameter A
has been instantiated to Int
.
为什么 TypeClassType 定义了两次
why type TypeClassType is defined twice
细化类型 Foo { type A = Int }
是 Foo
的一个更窄的子类型,类似于 Cat
是一个更窄的子类型动物
The refined type Foo { type A = Int }
is a narrower subtype of Foo
, similar to how Cat
is a narrower subtype of Animal
implicitly[(Foo { type A = Int }) <:< Foo]
implicitly[Cat <:< Animal]
因此,即使右侧表达式将 A
实例化为 Int
,左侧表达式也明确告诉编译器 foo<的静态类型/code> 只是更广泛的超类型
Foo
so even though the right-hand side expression instantiates A
as Int
, the left-hand side explicitly told the compiler that the static type of foo
is just the wider supertype Foo
val foo: Foo = new Foo {
type A = Int
def bar: A = ???
}
类似于编译器如何知道下面的 zar
静态类型只是更广泛的超类型 Animal
尽管 RHS 上的表达式指定了 Cat
similarly to how compiler knows that static type of zar
below is only the wider supertype Animal
despite the expression on the RHS specifying a Cat
val zar: Animal = new Cat
因此需要双重"类型说明
Hence the need for "double" type specification
val foo: Foo { type A = Int } = new Foo {
type A = Int
...
}
类似
val zar: Cat = new Cat
我们可以尝试依靠推理来推断出最具体的类型,但是当我们显式注释类型时,我们必须通过细化提供包括类型成员约束的完整信息.
We could try to rely on inference to deduce the most specific type, however when we are explicitly annotating types then we have to provide the full information which includes the type member constraints via refinements.
这篇关于函数定义中返回类型后的大括号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!