scala - 无形(scala)中的 "at"是什么?

标签 scala shapeless

我已经看到一个名为“at”的对象(可能是一个函数)散布在整个无形源和使用无形的代码中。特别是在对 this other question 的回答中使用了它.这是代码片段:

object iterateOverHList extends Poly1 {
  implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)
}

我知道它与 ~> 类型的 apply 方法有关。 “at”具体做什么,它在哪里定义?

最佳答案

PolyN#at的定义
at是使用 Poly 的通用方法.
~>applyspecial casePoly1 . apply这里用于使用 at 定义隐式方法:

implicit def caseUniv[T] = at[F[T]](apply(_))

方法atdefinedPolyN (例如在 Poly1 中)像这样:
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)或只是 at[Int](_.toString) (用于 apply 方法调用的语法糖)创建了一个 poly.Case[this.type, Int :: HNil]{ type Result = String } 的实例.

所以与 implicit def iterable[T, L[T] <: Iterable[T]] = at[L[T]](_.iterator)您创建一个隐式方法来创建 poly.Case[this.type, L[T] :: HNil]{ type Result = Iterator[T] } .

此隐式方法用于 map (以及其他一些多态函数)。
HList#map的实现
mapdefined像这样:
def map(f : Poly)(implicit mapper : Mapper[f.type, L]) : mapper.Out = mapper(l)

( LHList 的类型)

创建一个 Mapper编译器 looksCase1[Fn, T] .

对于 map(f)A :: B :: ... :: HNil编译器必须为 Case1[f.type, A] 找到隐式, Case1[f.type, B]等等。

如果是 List[Int] :: HNil唯一隐含的Case1需要的是Case1[f.type, List[Int]] .

请注意 Case1defined像这样:
type Case1[Fn, T] = Case[Fn, T :: HNil]

所以我们必须为 Case[f.type, List[Int] :: HNil] 找到一个隐含的值.

万一fobject搜索隐式的地方之一是 f领域和方法。所以编译器会发现Case定义于 f .

关于scala - 无形(scala)中的 "at"是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20912679/

相关文章:

scala - 在仅支持 Spark 1.6 的集群上使用 Spark 2.0 运行 Fat Jar

scala - 如何将SBT类附加到Intellij Idea?

scala - 如何在 Scala 中为列表实现自定义尾递归映射

scala - 无定型:通过镜盒类别或视场参数化的通用镜片

scala - 复杂层次数据结构的通用差异

Scala 类型语法

scala - 为什么编译器不引入依赖类型?

database - 在客户端和服务器之间共享的代码中表示 DB 实体的惯用方式

scala - 给定方法参数返回最具体的类型

Scala Lift - 连接到远程 MongoDB