什么是“在"?在无形(scala)? [英] What is "at" in shapeless (scala)?
问题描述
我看到一个名为at"的对象(可能是一个函数)散布在整个无形源代码和使用无形的代码中.特别是,它用于回答另一个问题.这是代码片段:
I've seen an object (probably a function) called "at" sprinkled throughout the shapeless source and in code that uses shapeless. In particular, it is used in the answer to this other question. Here is the code snippet:
object iterateOverHList extends Poly1 {
implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)
}
我知道它与 ~> 类型的 apply 方法有关.at"的具体作用是什么,它在哪里定义?
I've had some clue that it is related to the apply method of the ~> type. What specifically does "at" do, and where is it defined?
推荐答案
PolyN#at
的定义at
是使用 Poly
的通用方法.
Definition of PolyN#at
at
is a general way to work with Poly
.
~>
和 apply
是一个 特殊情况 Poly1
.apply
这里用来定义隐式方法,使用at
:
~>
with apply
is a special case of Poly1
. apply
here is used to define implicit method using at
:
implicit def caseUniv[T] = at[F[T]](apply(_))
方法 at
是 在 PolyN
中(例如在 Poly1
中)像这样:
Method at
is defined in PolyN
(for instance in Poly1
) like this:
trait PolyN extends Poly { outer =>
type Case[T1, T2, ..., TN] = poly.Case[this.type, T1 :: T2 :: ... :: TN :: HNil]
object Case {
type Aux[T1, T2, ..., TN, Result0] = poly.Case[outer.type, T1 :: T2 :: ... :: TN :: HNil] { type Result = Result0 }
}
class CaseBuilder[T1, T2, ..., TN] {
def apply[Res](fn: (T1, T2, ..., TN) => Res) = new Case[T1, T2, ..., TN] {
type Result = Res
val value = (l: T1 :: T2 :: ... :: TN :: HNil) => l match {
case a1 :: a2 :: ... :: aN :: HNil => fn(a1, a2, ..., aN)
}
}
}
def at[T1, T2, ..., TN] = new CaseBuilder[T1, T2, ..., TN]
}
如果是 Poly1
:
trait Poly1 extends Poly { outer =>
type Case[T1] = poly.Case[this.type, T1 :: HNil]
object Case {
type Aux[T1, Result0] = poly.Case[outer.type, T1 :: HNil] { type Result = Result0 }
}
class CaseBuilder[T1] {
def apply[Res](fn: (T1) => Res) = new Case[T1] {
type Result = Res
val value = (l: T1) => l match {
case a1 :: HNil => fn(a1)
}
}
}
def at[T1] = new CaseBuilder[T1]
}
所以 at[Int]
创建了一个 CaseBuilder[Int]
和 at[Int].apply[String](_.toString)
的实例code> 或只是 at[Int](_.toString)
(apply
方法调用的语法糖)创建一个 poly.Case[this.type,Int :: HNil]{ type Result = String }
.
So at[Int]
creates an instance of CaseBuilder[Int]
and at[Int].apply[String](_.toString)
or just at[Int](_.toString)
(synax sugar for apply
method call) creates an instance of poly.Case[this.type, Int :: HNil]{ type Result = String }
.
所以使用 implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)
你创建了一个隐式方法来创建a poly.Case[this.type, L[T] :: HNil]{ type Result = Iterator[T] }
.
So with implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)
you create an implicit method to create a poly.Case[this.type, L[T] :: HNil]{ type Result = Iterator[T] }
.
这个隐式方法用于map
(以及其他一些多态函数).
This implicit method is used in map
(and in some other polymorphic functions).
map
是 定义如下:
def map(f : Poly)(implicit mapper : Mapper[f.type, L]) : mapper.Out = mapper(l)
(L
是HList
的类型)
创建Mapper
编译器查找Case1[Fn, T]
.
对于 A :: B :: ... :: HNil
上的 map(f)
编译器必须为 Case1[f.type,A]
、Case1[f.type, B]
等.
For map(f)
on A :: B :: ... :: HNil
compiler have to find implicits for Case1[f.type, A]
, Case1[f.type, B]
and so on.
在 List[Int] :: HNil
的情况下,唯一需要的隐式 Case1
是 Case1[f.type, List[Int]]
.
In case of List[Int] :: HNil
the only implicit Case1
needed is Case1[f.type, List[Int]]
.
请注意,Case1
是 像这样定义:
type Case1[Fn, T] = Case[Fn, T :: HNil]
所以我们必须为 Case[f.type, List[Int] :: HNil]
找到一个隐含的值.
So we have to find an implicit value for Case[f.type, List[Int] :: HNil]
.
如果 f
是 object
搜索隐式的地方之一是 f
字段和方法.所以编译器会找到f
中定义的Case
.
In case f
is an object
one of the places to search for implicits is f
fields and methods. So compiler will find Case
defined in f
.
这篇关于什么是“在"?在无形(scala)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!