Functional Programming With Java 简明教程

Optionals and Monads

单子是函数式编程的一个关键概念。单子是一种设计模式,它有助于表示一个丢失的值。它允许封装一个潜在的 null 值,允许在它周围放置变换,并在存在时提取实际值。根据定义,单子是一组以下参数。

  1. A parametrized Type - M<T>

  2. A unit Function - T → M<T>

  3. A bind operation - M<T> bind T → M<U> = M<U>

Key Operations

  1. Left Identity - 如果一个函数绑定到特定值的一个单子上,那么它的结果将与将该函数应用于该值相同。

  2. Right Identity - 如果一个单子的返回方法与原始值的单子相同。

  3. Associativity - 可以在单子上以任何顺序应用函数。

Optional Class

Java 8 引入了 Optional 类,它是一个单子。它提供操作等同于单子的操作。例如, return 是一个获取值并返回单子的操作。Optional.of() 获取一个参数并返回 Optional 对象。在相同的基础上, bind 是一个将函数绑定到单子以生成单子的操作。Optional.flatMap() 是对 Optional 执行操作并将结果作为 Optional 返回的方法。

  1. A parametrized Type - Optional<T>

  2. A unit Function - Optional.of()

  3. A bind operation − Optional.flatMap()(可选)

Example − Left Identity

以下示例演示了如何让 Optional 类遵循左单位律。

import java.util.Optional;
import java.util.function.Function;

public class FunctionTester {
   public static void main(String[] args) {
      Function<Integer, Optional<Integer>> addOneToX
         = x −> Optional.of(x + 1);
      System.out.println(Optional.of(5).flatMap(addOneToX)
         .equals(addOneToX.apply(5)));
   }
}

Output

true

Example − Right Identity

以下示例演示了如何让 Optional 类遵循右单位律。

import java.util.Optional;

public class FunctionTester {
   public static void main(String[] args) {
      System.out.println(Optional.of(5).flatMap(Optional::of)
         .equals(Optional.of(5)));
   }
}

Output

true

Example - Associativity

以下示例演示了如何让 Optional 类遵循结合律。

import java.util.Optional;
import java.util.function.Function;

public class FunctionTester {
   public static void main(String[] args) {
      Function<Integer, Optional<Integer>> addOneToX
         = x −> Optional.of(x + 1);
      Function<Integer, Optional<Integer>> addTwoToX
         = x −> Optional.of(x + 2);
      Function<Integer, Optional<Integer>> addThreeToX
         = x −> addOneToX.apply(x).flatMap(addTwoToX);
      Optional.of(5).flatMap(addOneToX).flatMap(addTwoToX)
         .equals(Optional.of(5).flatMap(addThreeToX));
   }
}

Output

true