什么是“抽象过度"?意思? [英] What does "abstract over" mean?

查看:27
本文介绍了什么是“抽象过度"?意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经常在 Scala 文献中,我遇到抽象结束"这个词,但我不明白其意图.例如,Martin Odersky 写道

Often in the Scala literature, I encounter the phrase "abstract over", but I don't understand the intent. For example, Martin Odersky writes

您可以将方法(或函数")作为参数传递,或者您可以抽象它们.您可以将类型指定为参数,也可以抽象它们.

You can pass methods (or "functions") as parameters, or you can abstract over them. You can specify types as parameters, or you can abstract over them.

再举一个例子,在弃用观察者模式"论文中,

As another example, in the "Deprecating the Observer Pattern" paper,

我们的事件流是一流值的结果是我们可以抽象它们.

A consequence from our event streams being first-class values is that we can abstract over them.

我读过一阶泛型抽象于类型",而单子抽象于类型构造函数".我们还在蛋糕图案纸.引用许多这样的例子之一:

I have read that first order generics "abstract over types", while monads "abstract over type constructors". And we also see phrases like this in the Cake Pattern paper. To quote one of many such examples:

抽象类型成员提供了灵活的方式来抽象具体类型的组件.

Abstract type members provide flexible way to abstract over concrete types of components.

甚至相关的堆栈溢出问题也使用这个术语.不能对参数化类型进行存在抽象......"

Even relevant stack overflow questions use this terminology. "can't existentially abstract over parameterized type..."

那么……抽象"到底是什么意思?

So... what does "abstract over" actually mean?

推荐答案

在代数中,就像在日常概念形成中一样,抽象是通过按一些基本特征对事物进行分组并省略其特定的其他特征而形成的.抽象在表示相似性的单个符号或单词下统一.我们说我们抽象了差异,但这实际上意味着我们通过相似性整合.

In algebra, as in everyday concept formation, abstractions are formed by grouping things by some essential characteristics and omitting their specific other characteristics. The abstraction is unified under a single symbol or word denoting the similarities. We say that we abstract over the differences, but this really means we're integrating by the similarities.

例如,考虑一个程序,它对数字 123 求和:

For example, consider a program that takes the sum of the numbers 1, 2, and 3:

val sumOfOneTwoThree = 1 + 2 + 3

这个程序不是很有趣,因为它不是很抽象.我们可以抽象我们正在求和的数字,通过将所有数字列表整合到一个符号 ns 下:

This program is not very interesting, since it's not very abstract. We can abstract over the numbers we're summing, by integrating all lists of numbers under a single symbol ns:

def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)

而且我们也不特别关心它是一个列表.List 是一个特定的类型构造函数(接受一个类型并返回一个类型),但是我们可以通过指定我们想要的基本特征(它可以折叠)来抽象类型构造函数:

And we don't particularly care that it's a List either. List is a specific type constructor (takes a type and returns a type), but we can abstract over the type constructor by specifying which essential characteristic we want (that it can be folded):

trait Foldable[F[_]] {
  def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
}

def sumOf[F[_]](ns: F[Int])(implicit ff: Foldable[F]) =
  ff.foldl(ns, 0, (x: Int, y: Int) => x + y)

我们可以为 List 和任何其他我们可以折叠的东西提供隐式的 Foldable 实例.

And we can have implicit Foldable instances for List and any other thing we can fold.

implicit val listFoldable = new Foldable[List] {
  def foldl[A, B](as: List[A], z: B, f: (B, A) => B) = as.foldLeft(z)(f)
}

implicit val setFoldable = new Foldable[Set] {
  def foldl[A, B](as: Set[A], z: B, f: (B, A) => B) = as.foldLeft(z)(f)
}

val sumOfOneTwoThree = sumOf(List(1,2,3))

更重要的是,我们可以抽象操作数和操作数的类型:

What's more, we can abstract over both the operation and the type of the operands:

trait Monoid[M] {
  def zero: M
  def add(m1: M, m2: M): M
}

trait Foldable[F[_]] {
  def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
  def foldMap[A, B](as: F[A], f: A => B)(implicit m: Monoid[B]): B =
    foldl(as, m.zero, (b: B, a: A) => m.add(b, f(a)))
}

def mapReduce[F[_], A, B](as: F[A], f: A => B)
                         (implicit ff: Foldable[F], m: Monoid[B]) =
  ff.foldMap(as, f)

现在我们有一些非常普遍的东西.方法 mapReduce 将折叠任何 F[A] 给定我们可以证明 F 是可折叠的并且 A是一个幺半群或可以映射成一个.例如:

Now we have something quite general. The method mapReduce will fold any F[A] given that we can prove that F is foldable and that A is a monoid or can be mapped into one. For example:

case class Sum(value: Int)
case class Product(value: Int)

implicit val sumMonoid = new Monoid[Sum] {
  def zero = Sum(0)
  def add(a: Sum, b: Sum) = Sum(a.value + b.value)
}

implicit val productMonoid = new Monoid[Product] {
  def zero = Product(1)
  def add(a: Product, b: Product) = Product(a.value * b.value)
}

val sumOf123 = mapReduce(List(1,2,3), Sum)
val productOf456 = mapReduce(Set(4,5,6), Product)

我们已经抽象了幺半群和可折叠体.

We have abstracted over monoids and foldables.

这篇关于什么是“抽象过度"?意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆