Java 8을 사용한 모나드


78

모나드가 무엇인지 이해하는 데 도움이되도록 누군가 java를 사용하여 예제를 제공 할 수 있습니까? 가능합니까?

여기 http://jdk8.java.net/lambda/ 에서 시험판 람다 호환 JDK8을 다운로드하면 java를 사용하여 람다 식을 사용할 수 있습니다.

이 JDK를 사용하는 람다의 예가 아래에 나와 있습니다. 누군가 비교적 간단한 모나드를 제공 할 수 있습니까?

public interface TransformService {
        int[] transform(List<Integer> inputs);
    }
    public static void main(String ars[]) {
        TransformService transformService = (inputs) -> {
            int[] ints = new int[inputs.size()];
            int i = 0;
            for (Integer element : inputs) {
                ints[i] = element;
            }
            return ints;
        };

        List<Integer> inputs = new ArrayList<Integer>(5) {{
            add(10);
            add(10);
        }};
        int[] results = transformService.transform(inputs);
    }

1
방금 Java8 용 Try 모나드를 게시했습니다. github.com/jasongoodwin/better-java-monads
JasonG

해당 스트림, 선택 및 완료 가능 미래 gist.github.com/fmcarvalho/2be5ff6419f9d5d8df8c9c11fcd45271
Miguel Gamboa

어딘가에 ++ i가 필요합니다.
Ray Tayek

모나드는 통역사 패턴입니다.
Will Ness

답변:


78

참고 :

제안 된 JDK8 Optional 클래스 세 가지 모나드 법칙을 충족 합니다 . 여기에 그것을 보여주는 요점 이 있습니다.

모나드는 세 가지 법칙 을 따르는 두 가지 기능 을 제공하는 것뿐입니다 .

두 가지 기능 :

  1. 장소 모나드 맥락 값

    • Haskell 's Maybe : return/Just
    • Scala의 옵션 : Some
    • 기능적 자바의 옵션 : Option.some
    • JDK8의 옵션 : Optional.of
  2. 모나 딕 컨텍스트에서 함수 적용

    • Haskell 's Maybe : >>=(일명 bind)
    • Scala의 옵션 : flatMap
    • 기능적 자바의 옵션 : flatMap
    • JDK8의 옵션 : flatMap

세 가지 법칙에 대한 자바 데모 는 위의 요점 을 참조하십시오 .

참고 : 이해해야 할 핵심 사항 중 하나는 모나드 컨텍스트에서 적용 할 함수 의 서명입니다 . 원시 값 유형을 취하고 모나드 유형을 반환합니다.

즉,의 인스턴스가있는 경우 메서드에 Optional<Integer>전달할 수있는 함수 flatMap에는 서명이있을 것입니다 (Integer) -> Optional<U>. 여기서는 U여야 할 필요가없는 값 유형 Integer입니다. 예를 들면 String다음과 같습니다.

Optional<Integer> maybeInteger = Optional.of(1);

// Function that takes Integer and returns Optional<Integer>
Optional<Integer> maybePlusOne = maybeInteger.flatMap(n -> Optional.of(n + 1));

// Function that takes Integer and returns Optional<String>
Optional<String> maybeString = maybePlusOne.flatMap(n -> Optional.of(n.toString));

이런 식으로 코딩하거나 이런 식으로 생각하기 위해 모나드 인터페이스가 필요하지 않습니다. Scala에서는 Monad 인터페이스로 코딩하지 않습니다 (Scalaz 라이브러리를 사용하지 않는 한 ...). JDK8은 Java 사용자가 이러한 스타일의 연결 모나 딕 계산 을 사용할 수 있도록 지원할 것으로 보입니다 .

도움이 되었기를 바랍니다.

업데이트 : 여기에서 이에 대해 블로그를 작성했습니다 .


Java와 Scala 사이의 큰 차이는 모나 딕 for구조입니다. 모나드는 특별한 구문 지원 없이는 훨씬 덜 즐겁습니다.
Marko Topolnik

3
Java Optional는 실제 모나드가 아닙니다. 모나드 법칙은 다음을 생성하여 위반할 수 있기 때문입니다 null. developer.atlassian.com/blog/2015/08/optional-broken
Blaisorblade

1
@Blaisorblade 참조가 말하는 것이 아닙니다. 바인드 연산자로 사용 Optional되는 모나드 flatMap입니다.
lledr

56

Java 8에는 람다가 있습니다. 모나드는 완전히 다른 이야기입니다. Haskell과 Scala의 주제에 대한 많은 튜토리얼에서 알 수 있듯이 함수형 프로그래밍에서 설명하기에는 충분히 어렵습니다.

모나드는 정적으로 형식화 된 함수 언어의 전형적인 기능입니다. OO-speak로 설명하기 위해 Monad인터페이스를 상상할 수 있습니다. 구현을 구현할 때 '모나드 법칙'으로 알려진 것을 준수 한다면 구현하는 클래스를 Monad'모나드'라고 Monad합니다. 그런 다음 언어 는 클래스 인스턴스 작업을 흥미롭게 만드는 몇 가지 구문 설탕 을 제공합니다 Monad.

이제 IterableJava에서는 모나드와 관련이 없지만 Java 컴파일러가 특별히 처리하는 유형 ( foreachJava 5와 함께 제공 되는 구문) 의 예로 다음을 고려하십시오.

Iterable<Something> things = getThings(..);
for (Something s: things) {  /* do something with s */ }

따라서 이전 스타일의 루프 에서 IterableIterator메소드 ( hasNext및 회사)를 사용할 수 있었지만 forJava는이 구문 설탕을 특별한 경우로 허용 합니다.

따라서 구문 에서 유용하기 위해 법칙 (예 : 다음 요소가 없으면 반환 해야 함) 을 구현 Iterable하고 Iterator준수 해야하는 클래스와 마찬가지로 해당 표기법 (Haskell에서 호출 됨) 과 함께 유용한 모나 딕 클래스 가 여러 개 있을 수 있습니다. ) 또는 Scala의 표기법.IteratorhasNextfalseforeachdofor

그래서-

  1. 모나 딕 수업의 좋은 예는 무엇입니까?
  2. 그것들을 다루는 통사론 적 설탕은 어떤 모습일까요?

Java 8에서는 잘 모르겠습니다. 람다 표기법을 알고 있지만 다른 특수 구문 설탕에 대해서는 알지 못하므로 다른 언어로 예제를 제공해야합니다.

모나드는 종종 컨테이너 클래스로 사용됩니다 (목록은 예입니다). Java에는 이미 java.util.List모나 딕이 아닌 것이 있지만 여기에 Scala가 있습니다.

val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val result = for { // Iterate both lists, return a resulting list that contains 
                   // pairs of (Int, String) s.t the string size is same as the num.
  n <- nums        
  s <- strs if n == s.length 
} yield (n, s)
// result will be List((4, "hola")) 
// A list of exactly one element, the pair (4, "hola")

다음에 대한 (대략) 구문 설탕입니다.

val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val results = 
nums.flatMap( n =>                 
  strs.filter(s => s.size == n).   // same as the 'if'
       map(s => (n, s))            // Same as the 'yield'
)
// flatMap takes a lambda as an argument, as do filter and map
// 

이것은 목록 이해 를 제공하기 위해 모나드가 악용되는 Scala의 기능을 보여줍니다 .

소위 List는 스칼라의 모나드의 모든 모나드의 구현에 부합 있어야한다는 규정 법에 순종하기 때문에 스칼라는 모나드가있다 flatMap, map그리고 filter당신이 법률에 관심이 있다면 (방법, 블로그 항목이 가장 좋은 설명 I '를 갖고 "모나드는 코끼리입니다" 지금까지 찾았습니다). 그리고 보시다시피 람다 (및 HoF)는 절대적으로 필요 하지만 이러한 종류를 실용적인 방식으로 유용하게 만들기 에는 충분 하지 않습니다 .

container-ish 외에도 유용한 모나드가 많이 있습니다. 그들은 모든 종류의 응용 프로그램을 가지고 있습니다. 내가 가장 좋아하는 Option것은 스칼라의 Maybe모나드 (Haskell 의 모나드) 일 것이다. 이것은 널 안전성 을 가져 오는 래퍼 유형이다 . Option모나드 의 Scala API 페이지 는 아주 간단한 예제 사용법을 가지고있다 : http : //www.scala-lang. org / api / current / scala / Option.html Haskell에서 모나드는 비 모나 딕 Haskell 코드가 불확실한 실행 순서를 가지고 있다는 사실을 해결하는 방법으로 IO를 나타내는 데 유용합니다.

람다를 갖는 것은 함수형 프로그래밍 세계로 들어가는 작은 첫 걸음입니다. 모나드는 모나드 규칙 및 사용할 수 모나드 타입의 충분히 큰 세트를 모두 필요로 뿐만 아니라 그 재미 있고 유용한 작업을하게 문법 설탕을.

Scala는 (모나 딕) 함수형 프로그래밍도 허용하는 Java에 가장 가까운 언어이므로 (여전히) 관심이 있다면 Scala 용 Monad 자습서를 참조하십시오. http://james-iry.blogspot.jp/2007/09/ monads-are-elephants-part-1.html

쇼 인터넷 검색을 대충은 자바에서이 작업을 수행하는 적어도 하나 개의 시도가 있다는 것을 : https://github.com/RichardWarburton/Monads-in-Java -

안타깝게도 Java (람다 포함)로 모나드를 설명하는 것은 ANSI C (C ++ 또는 Java 대신)에서 본격적인 객체 지향 프로그래밍을 설명하는 것만 큼 어렵습니다.


yowzers, 감사합니다. 나는 여전히 어둠 속에 있고, 내 독서를 넓힐 것이고, 어쩌면 뛰어 들어서 스칼라를 시도 할 수도 있습니다.
NimChimpsky

4
예이! (Scala를 사용해 볼 수 있다는 소식을 들으 려면)-Scala에서 모나드를 적극적으로 배우지 않고도 많은 작업을 수행하고 생산성을 높일 수 있다는 것을 알게 될 것입니다. 그리고 언젠가 갑자기 이미 모나드를 잘 알고 있습니다!
Faiz

1
람다가없는 자바의 옵션 모나드 : functionaljava.org/examples/1.5/#Option.bind . 검색하면 Java에서 많은 FP를 찾을 수 있습니다.
pedrofurla

@ Faiz 그래서 정확히 "모나드"라는 용어는 무엇을 의미합니까 ?? 추상 메서드를 구현해야하는 또 다른 종류의 인터페이스입니까 ?? 간단히 말해서 어떤 사람이 "모나드"가 무엇인지 물으면 가장 짧은 대답은 무엇일까요?
nish1013 2013 년

2
나는 당신의 첫 번째 진술에 동의하지 않습니다. Haskell과 Scala의 모나드에 대한 많은 자습서가 설명하기 어렵다는 것을 나타내지 않는다고 생각합니다. 대신, 나는 그것들이 존재하는 것이 파워 모나드가 가져다주는 엄청난 다양성을 설명하기 위해 존재한다고 생각합니다. 모나드의 어려운 점은 매우 직관적이지만 정의하기 어렵다는 것입니다. 따라서 예를 들어 설명하는 것이 가장 효과적입니다.
DCKing 2014

11

모나드는 Java로 구현 될 수 있지만, 모나드를 포함하는 모든 계산은 제네릭과 중괄호가 뒤죽박죽이 될 운명입니다.

Java는 작업을 설명하거나 의미와 본질을 연구하기 위해 사용하는 언어가 아닙니다 . 이를 위해 JavaScript를 사용하거나 추가 비용을 지불하고 Haskell을 배우는 것이 훨씬 좋습니다.

어쨌든 새로운 Java 8 lambda를 사용하여 상태 모나드 를 구현했음을 알려드립니다 . 확실히 애완 동물 프로젝트이지만 사소한 테스트 케이스에서 작동합니다.

내 블로그 에서 찾을 수 있지만 여기에서 몇 가지 세부 정보를 제공하겠습니다.

상태 모나드는 기본적으로 상태에서 쌍 (state, content)으로의 함수입니다 . 일반적으로 상태에 일반 유형 S를 제공하고 콘텐츠에 일반 유형 A를 제공합니다.

Java에는 쌍이 없기 때문에 특정 클래스를 사용하여 모델링해야합니다. Scp (상태-콘텐츠 쌍)라고 부르겠습니다.이 경우에는 일반 유형 Scp<S,A>과 생성자를 갖습니다 new Scp<S,A>(S state,A content). 그런 다음 모나 딕 함수에 유형이 있다고 말할 수 있습니다.

java.util.function.Function<S,Scp<S,A>>

이는 @FunctionalInterface. 즉, 올바른 유형의 람다 식을 전달하여 이름을 지정하지 않고 유일한 구현 메서드를 호출 할 수 있습니다.

클래스 StateMonad<S,A>는 주로 함수를 감싸는 래퍼입니다. 생성자는 예를 들어 다음과 같이 호출 될 수 있습니다.

new StateMonad<Integer, String>(n -> new Scp<Integer, String>(n + 1, "value"));

상태 모나드는 함수를 인스턴스 변수로 저장합니다. 그런 다음 액세스하고 상태를 제공하는 공용 메소드를 제공해야합니다. 나는 그것을 s2scp( "state to state-content pair")라고 부르기로 결정했습니다 .

모나드의 정의를 완료하려면 유닛 (일명 return )과 bind (일명 flatMap ) 메소드를 제공해야합니다. 개인적으로 나는 단위를 정적으로 지정하는 것을 선호하지만 bind는 인스턴스 멤버입니다.

상태 모나드의 경우 단위는 다음과 같아야합니다.

public static <S, A> StateMonad<S, A> unit(A a) {
    return new StateMonad<S, A>((S s) -> new Scp<S, A>(s, a));
}

bind (인스턴스 멤버)는 다음과 같습니다.

public <B> StateMonad<S, B> bind(final Function<A, StateMonad<S, B>> famb) {
    return new StateMonad<S, B>((S s) -> {
        Scp<S, A> currentPair = this.s2scp(s);
        return famb(currentPair.content).s2scp(currentPair.state);
    });
}

bind는 이기종 상태 모나드의 연결을 허용하고이 모나드와 다른 모나드에 계산을 유형에서 유형으로 이동할 수있는 놀라운 기능을 제공하기 때문에 제네릭 유형 B를 도입해야합니다.

여기서는 Java 코드로 멈출 것입니다. 복잡한 것은 GitHub 프로젝트에 있습니다. 이전 Java 버전과 비교할 때 람다는 많은 중괄호를 제거하지만 구문은 여전히 ​​상당히 복잡합니다.

제쳐두고, 유사한 상태 모나드 코드가 다른 주류 언어로 작성되는 방법을 보여주고 있습니다. 스칼라의 경우, 바인드 (이 경우에 해야한다 라고 flatMap는 )처럼 읽고

def flatMap[A, B](famb: A => State[S, B]) = new State[S, B]((s: S) => {
  val (ss: S, aa: A) = this.s2scp(s)
  famb(aa).s2scp(ss)
})

JavaScript의 bind는 제가 가장 좋아하는 것입니다. 100 % 기능성, 가늘고 평균적이지만 물론 유형이 없습니다.

var bind = function(famb){
    return state(function(s) {
        var a = this(s);
        return famb(a.value)(a.state);
    });
};

<shameless> 여기서 몇 가지 모서리를 잘라 내고 있지만 세부 사항에 관심이 있다면 내 WP 블로그에서 찾을 수 있습니다. </ shameless>


1
나는 당신이 진지하고 유용한 대답을 가지고 있는지 의심하지 않지만, 그것의 중요한 부분 (실제로 Java에서 어떻게 구현했는지)은 링크 뒤에 숨겨져 있습니다. 링크는 시간이 지남에 따라 부실하므로 답변의 중요한 측면을 링크가 아닌 답변 자체에 포함해야하는 것이 SO의 정책입니다. 귀하가 링크 한 귀하의 페이지이기 때문에 가장 중요한 부분을 요약하고 여기에 귀하의 답변에 넣을 수 있습니다.
Erwin Bolwidt 2014

좋은 지적. 죄송합니다. 하루가 끝나기 전에 할게요. 는 그동안 나를 downvote하지 마십시오에서 :-) :-) :-) :-)
마르코 Faustinelli

5

모나드를 이해하는 유일한 방법은 여러 결합 자 라이브러리를 작성하고 결과 중복을 확인한 다음 모나드가이 중복을 제거 할 수 있음을 스스로 발견하는 것입니다. 이를 발견하면서 모든 사람은 모나드가 무엇인지에 대한 직관을 구축합니다.하지만이 직감은 다른 사람과 직접적으로 소통 할 수있는 종류가 아닙니다. 모든 사람이 구체적인 모나드로 일반화하는 것과 동일한 경험을해야하는 것 같습니다. 결합기 라이브러리의 예. 하나

여기서 몬 다스를 배울 수있는 자료를 찾았습니다.

당신에게도 유용하기를 바랍니다.

코드 커밋

james-iry.blogspot

debasishg.blogspot


1
그들은 모두 스칼라에 연결되어 있습니까? Java implentation을 찾고있었습니다
NimChimpsky 2011

Java 구현이 어려운 이유를 설명하려고했습니다.
Faiz

5

모나드는 이해하기 어려운 모나드에 관한 것입니다. 모나드는 특정 유형이 아니라 패턴입니다. 모나드는 모양이며, 구체적인 데이터 구조보다 더 추상적 인 인터페이스 (Java 의미가 아님)입니다. 결과적으로 모든 예제 기반 자습서는 불완전 성과 실패로 끝납니다. [...] 모나드를 이해하는 유일한 방법은 모나드가 무엇인지 확인하는 것입니다 : 수학적 구조.

Monads는 Daniel Spiewak의 은유가 아닙니다.


Java SE 8의 모나드

모나드 나열

interface Person {
    List<Person> parents();

    default List<Person> greatGrandParents1() {
        List<Person> list = new ArrayList<>();
        for (Person p : parents()) {
            for (Person gp : p.parents()) {
                for (Person ggp : p.parents()) {

                    list.add(ggp);
                }
            }
        }
        return list;
    }

    // <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
    default List<Person> greatGrandParents2() {
        return Stream.of(parents())
                .flatMap(p -> Stream.of(p.parents()))
                .flatMap(gp -> Stream.of(gp.parents()))
                .collect(toList());
    }
}

아마 모나드

interface Person {
    String firstName();
    String middleName();
    String lastName();

    default String fullName1() {
        String fName = firstName();
        if (fName != null) {
            String mName = middleName();
            if (mName != null) {
                String lName = lastName();
                if (lName != null) {
                    return fName + " " + mName + " " + lName;
                }
            }
        }
        return null;
    }

    // <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
    default Optional<String> fullName2() {
        return Optional.ofNullable(firstName())
                .flatMap(fName -> Optional.ofNullable(middleName())
                .flatMap(mName -> Optional.ofNullable(lastName())
                .flatMap(lName -> Optional.of(fName + " " + mName + " " + lName))));
    }
}

Monad는 중첩 된 제어 흐름 캡슐화를 위한 일반적인 패턴입니다 . 즉, 중첩 된 명령 관용구에서 재사용 가능한 구성 요소를 만드는 방법입니다.

모나드는 플랫 맵 작업이 있는 일반적인 래퍼 클래스가 아니라는 점을 이해하는 것이 중요 합니다. 예를 들어, ArrayList로모그래퍼 flatMap방법 모나드되지 않습니다. 모나드 법칙 은 부작용을 금지 하기 때문 입니다.

모나드는 형식주의 입니다. 내용이나 의미에 관계없이 구조를 설명합니다. 사람들은 무의미한 (추상적 인) 사물과 관련하여 어려움을 겪습니다. 그래서 그들은 모나드가 아닌 은유를 제시합니다.

참조 : Erik Meijer와 Gilad Bracha의 대화 .


자바에 있습니다 fName + " " + middleName()반환 할 수 없다 null, 그래서 Optional.ofNullable오해의 소지가있다. 아마 당신이 원 Optional.ofNullable(middleName()).map(mName -> fName + " " + mName)했나요?
Tagir Valeev 보낸

2

이 블로그 게시물 은 Java에서 Monad 유형 (인터페이스)을 구현 한 다음이를 사용하여 Maybe 모나드를 실제 애플리케이션으로 정의하는 방법에 대한 단계별 예제를 제공합니다.

이 게시물 은 Java 언어에 빌드 된 모나드가 하나임을 설명하며, 모나드는 많은 프로그래머가 생각하는 것보다 더 일반적이며 코더가 종종 실수로이를 재발 명 한다는 점을 강조 합니다 .



1

에 대한 모든 논란에도 불구하고 Optional만족 여부, 모나드 법률, 일반적으로보고 같은 I Stream, OptionalCompletableFuture같은 방법으로한다. 사실, 그들 flatMap()모두는 내가 신경 쓰는 전부이며 " 부작용의 세련된 구성 "(Erik Meijer 인용)을 받아 들일 수있게 해준다 . 우리는 할 수 있습니다 그래서 해당하는 Stream, Optional그리고 CompletableFuture다음과 같은 방법으로 :

Monads와 관련하여 저는 보통 다음과 같이 생각하기 만하면됩니다 flatMap()( Erik Meijer " Principles of Reactive Programming "과정에서).

Eric-Meijer-flatMap


0

저는 모나드를 좀 더 수학적 (하지만 여전히 비공식적) 방식으로 생각하고 싶습니다. 그 후 Java 8의 모나드 CompletableFuture 중 하나와의 관계를 설명 하겠습니다 .

우선, 모나드 M펑터 입니다. 즉, 유형을 다른 유형으로 변환합니다. If Xis a type (eg String) then we have another type M<X>(eg List<String>). 또한 X -> Y유형 의 변환 / 함수가있는 경우 함수 를 가져와야합니다 M<X> -> M<Y>.

그러나 그러한 모나드에는 더 많은 데이터가 있습니다. 우리는 X -> M<X>각 유형에 대한 기능인 소위 단위가 X있습니다. 즉,의 각 객체를 X모나드에 자연스럽게 래핑 할 수 있습니다.

그러나 모나드의 가장 특징적인 데이터는 제품입니다 : M<M<X>> -> M<X>각 유형에 대한 함수 입니다 X.

이 모든 데이터는 기능성, 연관성, 단위 법칙과 같은 일부 공리를 충족해야하지만 여기서 자세히 설명하지 않을 것이며 실제 사용에도 중요하지 않습니다.

에서 값 / 목적 : 이제 종종 등가 모나드 대한 정의, 결합 연산으로서 사용된다 모나드 또 다른 동작 추론 할 수있는 M<X>기능과 결합 될 수 X -> M<Y>있는 다른 값을 수득 하였다 M<Y>. 이를 어떻게 달성 할 수 있습니까? 음, 먼저 함수를 얻기 위해 함수에 기능성을 적용합니다 M<X> -> M<M<Y>>. 다음으로 함수를 얻기 위해 모나 딕 곱을 타겟에 적용합니다 M<X> -> M<Y>. 이제 M<X>값을 연결 M<Y>하여 원하는 값을 얻을 수 있습니다. 이 바인딩 작업은 여러 모나드 작업을 함께 연결하는 데 사용됩니다.

이제 CompletableFuture 예제, 즉 CompletableFuture = M. 객체를 CompletableFuture<MyData>비동기 적으로 수행되고 MyData결과적으로 미래에 객체를 산출하는 계산으로 생각하십시오 . 여기서 모나 딕 연산은 무엇입니까?

  • 기능성은 방법으로 실현됩니다 thenApply. 먼저 계산이 수행되고 결과가 나 오자마자 주어진 함수 thenApply가 적용되어 결과를 다른 유형으로 변환합니다.
  • 모나 딕 단위는 방법으로 실현 completedFuture됩니다. 문서에서 알 수 있듯이 결과 계산이 이미 완료되어 주어진 값을 한 번에 산출합니다.
  • 모나 딕 제품은 함수에 의해 실현되지 않지만 아래의 바인딩 작업은 (함수 성과 함께) 그와 동일하며 의미 론적 의미는 다음과 같습니다. CompletableFuture<CompletableFuture<MyData>>계산이 비동기 적으로 다른 계산을 생성하는 유형의 계산이 주어지면 CompletableFuture<MyData>결과적으로 일부 가치 MyData나중에 다른 총 수율을 계산 한 후 모두에서 연산을 수행하므로
  • 결과 바인딩 작업은 메서드에 의해 실현됩니다. thenCompose

보시다시피, 계산은 이제 특수한 컨텍스트, 즉 asynchronicity 로 래핑 될 수 있습니다 . 일반적인 모나드 구조를 사용하면 주어진 컨텍스트에서 이러한 계산을 연결할 수 있습니다. CompletableFuture예를 들어 Lagom 프레임 워크에서 (전용 스레드로 각 요청을 처리하는 대신) 효율적인 스레드 풀에 의해 투명하게 백업되는 비동기식 요청 처리기를 쉽게 구성 하는 데 사용됩니다 .


0

Java의 "선택적"모나드 다이어그램.

당신의 임무는 : 타입의 요소 변환은 "실제"(왼쪽)에 대한 작업을 수행 T 조합을 null 입력 U 조합을 null 빛 파란색 상자에서 함수합니다 (사용 연한 파란색 박스 기능을 ). 여기에는 하나의 상자 만 표시되지만 연한 파란색 상자의 체인이있을 수 있습니다 (따라서 유형 U union null 에서 유형 V_union null, type W union null 등으로 진행).

실제로 이것은 null함수 응용 프로그램 체인에 나타나는 값에 대해 걱정하게 합니다. 추한!

해결 방법 : 연한 녹색 상자 기능 을 사용하여 "옵션"(오른쪽)으로 이동 하여 T로 포장하십시오 . 여기 에서 빨간색 상자 함수를 사용하여 유형 요소를 유형 으로 변환 합니다 . "실제"에 기능 적용을 미러링하면 여러 개의 빨간색 상자 기능이 연결될 수 있습니다 (따라서 유형 에서 다음으로 진행됨). 마지막으로 짙은 녹색 상자 기능 중 하나를 통해 '옵션'에서 '실제'로 다시 이동 합니다 .Optional<T>Optional<T>Optional<U>Optional<U>Optional<V>Optional<W>

null더 이상 가치에 대해 걱정할 필요가 없습니다. 구현 적으로는 항상 Optional<U>, 비어 있거나 비어 있지 않을 수 있습니다. null 검사없이 빨간색 상자 함수에 대한 호출을 연결할 수 있습니다 .

요점 : 빨간색 상자 기능 은 개별적으로 직접 구현되지 않습니다. 대신, 또는 상위 함수 를 사용하여 파란색 상자 함수 (구현되어 사용 가능한 것, 일반적으로 하늘색 함수)에서 가져 map옵니다 flatMap.

회색 상자는 추가 지원 기능을 제공합니다.

단순함.

Java 선택 사항, 사용 방법

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.