[java] Java 8을 사용한 모나드

모나드가 무엇인지 이해하는 데 도움이되도록 누군가 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);
    }



답변

참고 :

제안 된 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 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 대신)에서 본격적인 객체 지향 프로그래밍을 설명하는 것만 큼 어렵습니다.


답변

모나드는 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>


답변

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

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

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

코드 커밋

james-iry.blogspot

debasishg.blogspot


답변

모나드는 이해하기 어려운 모나드에 관한 것입니다. 모나드는 특정 유형이 아니라 패턴입니다. 모나드는 모양이며, 구체적인 데이터 구조보다 더 추상적 인 인터페이스 (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의 대화 .


답변

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

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


답변

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

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

Eric-Meijer-flatMap


댓글 달기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다