我会给出一个更广泛的答案,希望你不要介意。
ADT,或代数数据类型,可以分为sum types和product types。这不是 Scala 特有的,而是一个通用的函数式编程概念。
产品类型包括几个底层类型,它们之间有一个隐含的布尔和。例如,学生是 FirstName and LastName and Age and CoursesEnrolled。另一方面,Sum 类型在它们之间有一个隐含的 或。例如,汽车是保时捷或奥迪或法拉利。
在 Scala 中,产品类型最常被建模为案例类,而总和类型被建模为层次结构,其中基本特征或抽象类被所有可能的实例(通常是案例类)继承。鉴于我们之前的示例,学生将是一个
case class Student(firstName: String, lastName: String, age: Int, classesEnrolled: Vector[Course])
而汽车将是一个
sealed trait Car
trait Porsche extends Car
trait Audi extends Car
trait Ferrari extends Car
对于 sum 类型,有很多小的设计选择,例如使用特征或抽象类作为基础,是否使用特征或案例类作为实例等。我现在不打算讨论。另外,仅供参考:在面向 FP 的 Scala 库(例如 scalaz、cats、shapeless 等)中,还有其他方便的产品和总和类型表示。
Sum 类型可以有两个或多个不同的值;我们的汽车示例有三个。通常我们只需要两个——Option、Either、Future、Try 只是 vanilla Scala 中的 sum 类型的一些示例,它们只有两个可能的值。在这些情况下,我们可以使用map 和flatMap 将函数应用于“快乐场景”(一些用于选项,Right 用于 Either 等)的值,否则保持不变(在 None 的情况下,左等)。
但是,这只有在所讨论的总和类型是右偏时才有可能。右偏意味着诸如map 和flatMap 之类的函数仅适用于“右侧”或“快乐的一侧”,而另一侧保持不变。在 Scala 2.12 之前,Either 是无偏见的,这意味着你不能只取一个 Either 的东西并映射它。目前还不清楚映射函数应该应用于右还是左。您需要使用“正确的投影”以使其具有右偏性,因此可映射和可平面映射(这也意味着它可以用于理解等,因此非常方便)。
但正如我所说,使用 Scala 2.12。它变得偏右,恕我直言,这是一个更好的设计选择,并且与其他库中的其他类似总和类型完美匹配。例如,现在很容易从 Either 转到 \/ (scalaz dictjuntion),因为没有偏差不匹配。它们是完全同构的。
我不确定您所说的“它与 Function1 有什么关系”是什么意思。它是一个参数的函数。这是您用于 map 和 flatMap 前面示例中的二值数据类型(Option、Either 等)的方法。