State MonadState Monad 可以在计算中附加任意类型的状态值。State Monad 与 Reader Monad 相似,只是 State Monad 在转换时会返回一个新的状态对象,从而可以描述可变的环境。State Monad 的类型构造器从类型 T 中创建一个函数类型,该函数类型的参数是状态对象的类型 S,而返回值包含类型 S 和 T 的值。State Monad 的 unit 操作返回的函数只是简单地返回输入的类型 S 的值;bind 操作所返回的函数类型负责在执行时传递正确的状态对象。
清单 10 给出了 State Monad 的示例。State Monad 使用元组 Tuple2<T, S> 来保存计算值和状态对象,所对应的一元类型是 Function<S, Tuple2<T, S>> 表示的函数。unit 方法所返回的函数只是简单地返回输入状态对象。bind 方法的转换逻辑使用 input.apply(s) 得到 T1 和 S 的值,再用得到的 S 值调用 transform。
清单 10. State Monad 示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| public class StateMonad {
public static <T, S> Function<S, Tuple2<T, S>> unit(T value) {
return s -> Tuple.of(value, s);
}
public static <T1, T2, S> Function<S, Tuple2<T2, S>>
bind(Function<S, Tuple2<T1, S>> input,
Function<T1, Function<S, Tuple2<T2, S>>> transform) {
return s -> {
Tuple2<T1, S> result = input.apply(s);
return transform.apply(result._1).apply(result._2);
};
}
public static void main(String[] args) {
Function<String, Function<String, Function<State, Tuple2<String,
State>>>> transform =
prefix -> value -> s -> Tuple
.of(prefix + value, new State(s.getValue() +
value.length()));
Function<State, Tuple2<String, State>> m1 = unit("Hello");
Function<State, Tuple2<String, State>> m2 = bind(m1,
transform.apply("1"));
Function<State, Tuple2<String, State>> m3 = bind(m2,
transform.apply("2"));
Tuple2<String, State> result = m3.apply(new State(0));
System.out.println(result);
}
}
|
State Monad 中使用的状态对象如清单 11 所示。State 是一个包含值 value 的不可变对象。清单 10 中的 m1 封装了值 Hello。transform 方法用来从输入的字符串前缀 prefix 中创建转换函数。转换函数会在字符串值上添加给定的前缀,同时会把字符串的长度进行累加。转换函数每次都返回一个新的 State 对象。转换之后的结果中字符串的值是 21Hello,而 State 对象中的 value 为 11,是字符串 Hello 和 1Hello 的长度相加的结果。
清单 11. 状态对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| public class State {
private final int value;
public State(final int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public String toString() {
return "State{" +
"value=" + value +
'}';
}
}
|
|