w ^adler, Philip , 2001
Read this post in spanish
Monad是数学和函数式编程之间共享的众多概念之一。 它来自类别理论,用于解决异常控制,计数器或执行跟踪之类的问题。 在命令式语言中,此问题很容易攻击,但在纯语言中则可能有些复杂。
纯函数式语言具有此优势:所有数据流都是明确的。 这个缺点:有时很明显。
本文解释了这种显式数据流如何提高模块性以及此功能在编程中的重要性。
本文解释了这种显式数据流如何提高模块性以及此功能在编程中的重要性。
monad,也称为标准构造,是一种封装行为的数据结构。 这种行为通常在命令式编程中作为副作用实现。 理解monad的一个关键示例是封装异常的Scala或VAVR(JAVA的功能数据结构)中的Try值。 在最终应用之前,此值可用于组成函数,而无需显式管理每个可能的错误。
public static Try<Integer> divide(Integer dividend, Integer divider) {
return Try.of(() -> dividend/divider);
}
public static void main(String[] args) {
Try<Integer> result = divide(100, 0).flatMap(r1 -> divide(r1, 10));
System.out.println("RESULT 1 = " + resultado.map(String::valueOf)
.getOrElseGet(Throwable::getMessage));
// RESULT 1 = / by zero
result = divide(100, 10).flatMap(r1 -> divide(r1, 10));
System.out.println("RESULT 2 = " + resultado.map(String::valueOf)
.getOrElseGet(Throwable::getMessage));
// RESULT 2 = 1
}
Monads Laws
monad的正式定义包括3条确定结构是否为monad的法律。 该定律可能具有更多的理论价值,而不是实用价值,但是此博客是关于:P的,因此我将尝试解释其原理。
Left Unit/Left Identity
该法则规定,如果您使用正确的构图(根据函数的返回值使用map或flatMap),则将函数应用于值并应用于内部具有相同值的monad应该相等。
public static void main(String[] args) {
Integer hundred = 100;
Try<Integer> tryHundred = Try.of(() -> hundred);
Boolean r = tryHundred.flatMap(value -> divide(100, value))
.equals(divide(100, hundred));
// True
}
return a >>= f = f
Right Unit/Right Identity
像以前的定律一样,如果我们有一个接收值并将结果封装在monad中的函数,则将其应用于该值或与另一个monad函数组合的结果应相同。
public static void main(String[] args) {
Integer hundred = 100;
Try<Integer> tryHundred = Try.of(() -> hundred);
// success return the same value encapsulated in a Try but cannot catch exceptions
Boolean r = tryHundred.flatMap(value -> Try.success(value))
.equals(Try.success(hundred));// True
}
m >>= return = m
JAVA中的此示例似乎具有相同的实现,但是在Haskell中,这两个定律之间的差异更加明显。 就像我说的那样,这条定律是理论上的,Haskell是纯函数的,更接近数学。
Associativity
关联性法则说,我们应该能够顺序组成函数或将一个函数作为另一个函数的输入。
public class MonadTest {
public static Try<Integer> divideByTen(Integer dividend) {
return Try.of(() -> dividend/10);
}
public static Try<Integer> doubleVal(Integer n1) {
return Try.of(() -> n1 * 2);
}
public static void main(String[] args) {
Try<Integer> tryHundred = Try.of(() -> 100);
Try<Integer> r1 = tryHundred.flatMap(MonadTest::divideByTen).flatMap(doubleVal::doubleVal);
Try<Integer> r2 = tryHundred.flatMap(
hundred -> divideByTen(hundred).flatMap(MonadTest::doubleVal)
);
Boolean r = r1.equals(r2);// True
}
}
(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
721

被折叠的 条评论
为什么被折叠?



