Java 8中的Streams是monad吗?

时间:2014-01-06 04:38:34

标签: functional-programming java-8 monads java-stream

好像是Optional in Java 8 is a monad

Streams也是monad吗?

任何人都可以识别endofunctor和可选monad中的两个自然变换吗?

3 个答案:

答案 0 :(得分:11)

编辑以下答案为不正确(此处保留为历史记录)。

  

是的,在每种情况下,仿函数都由类及其map方法组成,两个自然变换是offlatMap(identity)

正确答案似乎是here

答案 1 :(得分:2)

如果您了解Haskell:Java的流不是别的,那么Haskell的列表monad []和Java的Optional就是Haskell的Maybe monad。

答案 2 :(得分:2)

是的,java.util.stream.Stream符合Monad法律。

满足以下先决条件:

  1. Stream应该是 Functor ,即提供以下功能fmap :: (a -> b) -> M a -> M b。 如果我们查看源代码,将会看到它已经具有功能Stream<R> map(Function<T, R> mapper)

  2. 它应具有unit(又称return)操作:unit :: a -> M a。显而易见:Stream<T> of(T t)

  3. 它应该具有bind join操作:

    1. bind :: M a -> (a -> M b) -> M b Stream<R> flatMap(Function<T, Stream<R>> mapper)
    2. join :: M (M a) -> M a Stream中没有这个,但是我们可以从bind推断出来。

现在我们具有必需的功能。但这还不够吗?我们需要证明单子法则是有效的。让我们看看它们:

左身份: (return a) bind f <=> f a

        Function<String, Stream<Integer>> f = str -> str.chars().boxed();
        String a = "abc";
        Stream<Integer> left = Stream.of(a).flatMap(f);
        Stream<Integer> right = f.apply(a);
        //left should be same as right

右身份: m bind unit <=> m

        Stream<String> stream = Stream.of("abc", "def");
        Stream<String> left = stream.flatMap(str -> Stream.of(str));
        // left should be same as Stream.of("abc", "def")

关联性: (m bind f) bind g <=> m bind (\x -> f x bind g)


        Function<Integer, Stream<String>> f = integer -> Arrays.stream(Integer.toHexString(integer).split(""));
        Function<String, Stream<BigInteger>> g = string -> Stream.of(string).map(str -> new BigInteger(str, 16));

        Stream<Integer> mLeft = Stream.of(47789, 61453);
        Stream<BigInteger> left = mLeft.flatMap(f).flatMap(g);

        Stream<Integer> mRight = Stream.of(47789, 61453);
        Stream<BigInteger> right = mRight.flatMap(integer -> f.apply(integer).flatMap(g));
        //left should be same as right        

因此,看起来Streams确实是monads!但是请注意,Optional可能会发生同样的情况,有时会违反摩纳哥法律。如果您知道可能发生的情况,请在下面评论。