Java 8中的Streams是monad吗?

Ray*_*yek 17 monads functional-programming java-8 java-stream

似乎Java 8中Optional是monad.

Streams也是monad吗?

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

n. *_* m. 11

编辑下面的答案是错误的(保留在历史记录中).

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

正确答案似乎在这里.

  • 该链接很好,但没有简单的方法可以查看答案是“是”还是“否”。请考虑更新您的问题,以便人们可以快速看到简短的答案是什么。 (2认同)

Igo*_*nko 5

是的,java.util.stream.Stream满足单子定律。

以下先决条件是:

  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 bStream<R> flatMap(Function<T, Stream<R>> mapper)
    2. join :: M (M a) -> M a:这个在 中不存在Stream,但我们可以从 中推断出来bind

现在我们已经有了所需的功能。但仅仅称其为 monad 还不够!我们需要证明单子定律是有效的。让我们看看它们:

左身份: (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
Run Code Online (Sandbox Code Playgroud)

正确身份: 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")
Run Code Online (Sandbox Code Playgroud)

关联性: (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        

Run Code Online (Sandbox Code Playgroud)

所以看起来 Streams 确实是 monad!但要小心,同样的情况也可能发生,就像Optional有时违反一元法则一样。我有一种直觉,如果您使用它,在某些情况下可能会违反它,parallel()因为它可以更改执行顺序。如果您知道它可能发生在哪里,请在下面发表评论。