Functional programming 流是否在Java8Monad中?

Functional programming 流是否在Java8Monad中?,functional-programming,java-8,monads,java-stream,Functional Programming,Java 8,Monads,Java Stream,这似乎是一个好消息 溪流也是单子吗 有人能识别可选单子中的内函子和两个自然变换吗?编辑下面的答案是不正确的(保留在这里作为历史记录) 是的,在每种情况下,函子都由类及其map方法组成,两种自然转换是of和flatMap(identity) 正确的答案似乎是。如果你知道Haskell:Java的流不是别的,那么Haskell的列表monad[]和Java的可选项不是别的,Haskell的可能是monad。是的,Java.util.Stream.Stream满足monad定律 以下先决条件是: St

这似乎是一个好消息

溪流也是单子吗


有人能识别可选单子中的内函子和两个自然变换吗?

编辑下面的答案是不正确的(保留在这里作为历史记录)

是的,在每种情况下,函子都由类及其
map
方法组成,两种自然转换是
of
flatMap(identity)


正确的答案似乎是。

如果你知道Haskell:Java的流不是别的,那么Haskell的列表monad[]和Java的可选项不是别的,Haskell的可能是monad。

是的,
Java.util.Stream.Stream
满足monad定律

以下先决条件是:

  • Stream
    应该是Functor,即提供以下函数
    fmap::(a->b)->ma->mb
    。 如果我们查看源代码,就会发现它已经有函数
    流映射(函数映射器)

  • 它应该有
    unit
    (也称为
    return
    )操作:
    unit::a->ma
    。这一点很明显:
    流(T)

  • 它应该具有
    bind
    操作:

  • bind::MA->(a->MB)->MB
    流平面图(函数映射器)
  • join::M(ma)->ma
    :这一个在
    流中不存在,但我们可以从
    bind
    中推断出来
  • 现在我们有了必要的功能。但还不足以称之为monad!我们需要证明单子定律是有效的。让我们来看看它们:

    左标识:
    (返回a)绑定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
    
    函数f=str->str.chars().boxed();
    字符串a=“abc”;
    流左=流(a).flatMap(f);
    右流=f.apply(a);
    //左边应该和右边一样
    
    右标识:
    m绑定单位m

    Stream=Stream.of(“abc”、“def”);
    Stream left=Stream.flatMap(str->Stream.of(str));
    //左侧应与“abc”、“def”流相同
    
    关联性:
    (m bind f)bind g m bind(\x->f x bind g)

    
    函数f=integer->Arrays.stream(integer.toHexString(integer.split)(“”);
    函数g=string->Stream.of(string.map)(str->newbiginger(str,16));
    流mLeft=流of(4778961453);
    左流=mLeft.flatMap(f).flatMap(g);
    溪流mRight=溪流of(4778961453);
    Stream right=mRight.flatMap(整数->f.apply(整数).flatMap(g));
    //左边应该和右边一样
    

    看来溪流真的是单子!但是要小心,同样的情况也可能发生在
    可选的
    上,它有时会违反一元法则。我有一种直觉,如果您使用
    parallel()
    ,在某些情况下可能会违反它,因为它可以更改执行顺序。如果您知道可能发生的情况,请在下面进行评论。

    我想您对Streams不太了解。然而,这又有什么关系呢?在Java中不能抽象类型构造函数,也不能重载返回类型,因此可能无法编写monad构造函数中多态的Java代码。值得注意的是,Optional在处理null值时违反了左标识定律,因此从技术上讲不是monad
    Optional.ofNullable(null).flatMap(Optional::of)
    生成一个空的Optional,而
    Optional.of(null)
    抛出一个NPE。当然,它仍然提供了monad的大部分好处。我们需要定义:\displaystyle\begin{array}{lcl}\mathit{return}&:&a\rightarrow\mathit{Stream},a\\\ mathit{join}&:&\mathit{Stream},(\mathit{Stream},a)\rightarrow\mathit{Stream},a\end{array}链接很好,但要想知道答案是“是”还是“否”,并没有简单的方法。请考虑更新你的问题,这样人们就可以很快地看到答案是什么。@ TITROM我想删除我的答案,因为它是错误的,但是不会让我。@ N.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")
    
    
            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