Monaden mit Java 8

78

Kann jemand ein Beispiel für die Verwendung von Java geben, um zu verstehen, was eine Monade ist? Sind sie möglich?

Lambda-Ausdrücke sind mit Java möglich, wenn Sie das Lambda-kompatible JDK8 vor der Veröffentlichung von hier herunterladen: http://jdk8.java.net/lambda/

Ein Beispiel für ein Lambda, das dieses JDK verwendet, ist unten dargestellt. Kann jemand eine vergleichsweise einfache Monade bereitstellen?

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);
    }
NimChimpsky
quelle
1
Ich habe gerade eine Try-Monade für Java8 veröffentlicht. github.com/jasongoodwin/better-java-monads
JasonG
Entsprechender Stream, optional und vollständigFuture gist.github.com/fmcarvalho/2be5ff6419f9d5d8df8c9c11fcd45271
Miguel Gamboa
du brauchst irgendwo ein ++ i.
Ray Tayek
Monade ist das Interpretermuster.
Will Ness

Antworten:

78

Nur zu deiner Information:

Die vorgeschlagene optionale JDK8- Klasse erfüllt die drei Monadengesetze . Hier ist ein Kern, der das demonstriert .

Eine Monade braucht nur zwei Funktionen, die drei Gesetzen entsprechen.

Die zwei Funktionen:

  1. Platzieren Sie einen Wert in einem monadischen Kontext

    • Haskell's Vielleicht: return/Just
    • Scalas Option: Some
    • Funktionale Java-Option: Option.some
    • JDK8 ist optional: Optional.of
  2. Wenden Sie eine Funktion im monadischen Kontext an

    • Haskell's Vielleicht: >>=(aka bind)
    • Scalas Option: flatMap
    • Funktionale Java-Option: flatMap
    • JDK8 ist optional: flatMap

In der obigen Übersicht finden Sie eine Java-Demonstration der drei Gesetze.

HINWEIS: Eines der wichtigsten Dinge, die zu verstehen sind, ist die Signatur der Funktion, die im monadischen Kontext angewendet werden soll : Sie verwendet den Rohwerttyp und gibt den monadischen Typ zurück.

Mit anderen Worten, wenn Sie eine Instanz von haben Optional<Integer>, haben die Funktionen, die Sie an ihre flatMapMethode übergeben können, die Signatur (Integer) -> Optional<U>, wobei Ues sich um einen Werttyp handelt, der nicht sein muss Integer, zum Beispiel 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));

Sie benötigen keine Monadenschnittstelle, um auf diese Weise zu codieren oder so zu denken. In Scala codieren Sie nicht in eine Monad-Schnittstelle (es sei denn, Sie verwenden die Scalaz-Bibliothek ...). Es scheint, dass JDK8 Java-Leuten die Möglichkeit geben wird, diesen Stil verketteter monadischer Berechnungen ebenfalls zu verwenden.

Hoffe das ist hilfreich!

Update: gebloggt dieses hier .

ms-tg
quelle
Die große Lücke zwischen Java und Scala ist das monadische forKonstrukt. Monaden sind ohne diese spezielle syntaktische Unterstützung weitaus weniger unterhaltsam.
Marko Topolnik
3
Java Optionalist keine echte Monade, da null
Monadengesetze
1
@Blaisorblade Das sagt Ihre Referenz nicht. Optionalist eine Monade mit flatMapdem Bindungsoperator.
lledr
55

Java 8 wird Lambdas haben; Monaden sind eine ganz andere Geschichte. Sie sind schwer genug in der funktionalen Programmierung zu erklären (wie die große Anzahl von Tutorials zu diesem Thema in Haskell und Scala zeigt).

Monaden sind ein typisches Merkmal statisch typisierter Funktionssprachen. Um sie in OO-Sprache zu beschreiben, können Sie sich eine MonadSchnittstelle vorstellen . Klassen, die implementiert werden, Monadwürden dann als "monadisch" bezeichnet, vorausgesetzt, dass bei der Implementierung Monadder Implementierung die sogenannten "Monadengesetze " eingehalten werden. Die Sprache bietet dann etwas syntaktischen Zucker , der die Arbeit mit Instanzen der MonadKlasse interessant macht.

Jetzt Iterablein Java hat nichts mit Monaden zu tun, sondern als ein Beispiel für eine Art , dass die Java - Compiler behandelt speziell (die foreachSyntax , die mit Java 5 kam), bedenken Sie:

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

Während wir also haben könnten verwendet Iterable‚s IteratorMethoden ( hasNextund Unternehmen) in einer alten Stil forSchleife, Java gewährt uns diesen syntaktischen Zucker als Sonderfall .

So wie Klassen, die die Gesetze implementieren Iterableund Iteratorbefolgen müssen Iterator(Beispiel: hasNextmuss zurückgegeben werden, falsewenn es kein nächstes Element gibt), um in der foreach Syntax nützlich zu sein, würde es mehrere monadische Klassen geben, die mit einer entsprechenden doNotation nützlich wären (wie sie in Haskell genannt wird) ) oder Scalas forNotation.

Damit -

  1. Was sind gute Beispiele für monadische Klassen?
  2. Wie würde syntaktischer Zucker für den Umgang mit ihnen aussehen?

In Java 8 weiß ich es nicht - mir ist die Lambda-Notation bekannt, aber mir ist kein anderer spezieller syntaktischer Zucker bekannt, daher muss ich Ihnen ein Beispiel in einer anderen Sprache geben.

Monaden dienen oft als Containerklassen (Listen sind ein Beispiel). Java hat bereits java.util.Listwas offensichtlich nicht monadisch ist, aber hier ist Scalas:

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")

Welches ist (grob) syntaktischer Zucker für:

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
// 

Dies zeigt eine Funktion von Scala, bei der Monaden genutzt werden, um Listenverständnisse zu vermitteln .

Ein Listin Scala ist also eine Monade, weil es den Monadengesetzen von Scala entspricht, die vorschreiben, dass alle Monadenimplementierungen konform sein müssen flatMap, mapund filterMethoden (wenn Sie an den Gesetzen interessiert sind, hat der Blogeintrag "Monaden sind Elefanten" die beste Beschreibung I ' habe bisher gefunden). Und wie Sie sehen können, sind Lambdas (und HoF) absolut notwendig, aber nicht ausreichend , um solche Dinge auf praktische Weise nützlich zu machen.

Neben den Container-Monaden gibt es auch eine Reihe nützlicher Monaden. Sie haben alle Arten von Anwendungen. Mein Favorit muss die OptionMonade in Scala sein (die MaybeMonade in Haskell), ein Wrapper-Typ, der keine SicherheitOption bietet : Die Scala-API-Seite für die Monade hat ein sehr einfaches Beispiel: http: //www.scala-lang. org / api / current / scala / Option.html In Haskell sind Monaden nützlich, um E / A darzustellen, um die Tatsache zu umgehen , dass nicht-monadischer Haskell-Code eine unbestimmte Ausführungsreihenfolge hat.

Lambdas zu haben ist ein erster kleiner Schritt in die Welt der funktionalen Programmierung. Monaden erfordern sowohl die Monadenkonvention als auch einen ausreichend großen Satz verwendbarer monadischer Typen sowie syntaktischen Zucker, damit die Arbeit mit ihnen Spaß macht und nützlich ist.

Da Scala wohl die Java am nächsten liegende Sprache ist, die auch (monadische) funktionale Programmierung ermöglicht, schauen Sie sich dieses Monad-Tutorial für Scala an, wenn Sie (noch) interessiert sind: http://james-iry.blogspot.jp/2007/09/ Monaden-sind-Elefanten-Teil-1.html

Ein flüchtiges Googeln zeigt, dass es in Java mindestens einen Versuch gibt, dies zu tun: https://github.com/RichardWarburton/Monads-in-Java -

Leider ist das Erklären von Monaden in Java (auch mit Lambdas) genauso schwierig wie das Erklären der vollständigen objektorientierten Programmierung in ANSI C (anstelle von C ++ oder Java).

Faiz
quelle
yowzers, danke. Ich bin immer noch ein bisschen im Dunkeln, werde meine Lektüre erweitern und vielleicht sogar den Sprung wagen und eine Scala probieren.
NimChimpsky
4
Yay! (um zu hören, dass Sie Scala ausprobieren könnten) - Sie werden feststellen, dass Sie eine Menge Dinge erledigen können, super produktiv sind, ohne aktiv Monaden in Scala zu lernen - und dann werden Sie eines Tages aus heiterem Himmel plötzlich feststellen, dass Sie kenne Monaden schon ganz gut!
Faiz
1
Die Option Monade in Java ohne Lambdas: Functionaljava.org/examples/1.5/#Option.bind . Durchsuchen Sie und Sie können viele FP in Java finden.
Pedrofurla
@Faiz also was genau bedeutet "Monade" Begriff? Ist es eine andere Art von Schnittstelle, die abstrakte Methoden implementieren muss? Kurz gesagt, wenn jemand fragen würde, was "Monade" ist, was wäre die kürzeste Antwort?
Nish1013
2
Ich bin mit Ihrer ersten Aussage nicht einverstanden. Ich glaube nicht, dass die große Anzahl von Tutorials zu Monaden für Haskell und Scala darauf hindeutet, dass sie schwer zu erklären sind. Stattdessen denke ich, dass sie existieren, um die große Vielfalt der Machtmonaden zu erklären. Das Schwierige an Monaden ist, dass sie zwar sehr intuitiv, aber schwer zu definieren sind. Daher ist eine Erklärung am Beispiel am effektivsten.
DCKing
11

Obwohl Monaden in Java implementiert werden können, ist jede Berechnung, die sie betrifft, dazu verdammt, eine chaotische Mischung aus Generika und geschweiften Klammern zu werden.

Ich würde sagen, dass Java definitiv nicht die Sprache ist, die verwendet wird, um ihre Arbeit zu veranschaulichen oder ihre Bedeutung und Essenz zu studieren. Zu diesem Zweck ist es weitaus besser, JavaScript zu verwenden oder einen zusätzlichen Preis zu zahlen und Haskell zu lernen.

Wie auch immer, ich signalisiere Ihnen, dass ich gerade eine Zustandsmonade mit den neuen Java 8-Lambdas implementiert habe . Es ist definitiv ein Haustierprojekt, aber es funktioniert in einem nicht trivialen Testfall.

Sie finden es vielleicht in meinem Blog , aber ich werde Ihnen hier einige Details geben.

Eine Zustandsmonade ist im Grunde eine Funktion von einem Zustand zu einem Paar (Zustand, Inhalt) . Normalerweise geben Sie dem Status einen generischen Typ S und dem Inhalt einen generischen Typ A.

Da Java keine Paare hat, müssen wir sie mit einer bestimmten Klasse modellieren. Nennen wir es Scp (State-Content-Paar), das in diesem Fall einen generischen Typ Scp<S,A>und einen Konstruktor hat new Scp<S,A>(S state,A content). Danach können wir sagen, dass die monadische Funktion einen Typ haben wird

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

das ist ein @FunctionalInterface. Das heißt, dass die einzige Implementierungsmethode aufgerufen werden kann, ohne sie zu benennen, wobei ein Lambda-Ausdruck mit dem richtigen Typ übergeben wird.

Die Klasse StateMonad<S,A>ist hauptsächlich ein Wrapper um die Funktion. Sein Konstruktor kann zB mit aufgerufen werden

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

Die Zustandsmonade speichert die Funktion als Instanzvariable. Es ist dann notwendig, eine öffentliche Methode bereitzustellen, um darauf zuzugreifen und es dem Staat zuzuführen. Ich habe beschlossen, es zu nennen s2scp("State-to-State-Content-Paar").

Um die Definition der Monade zu vervollständigen, müssen Sie eine Unit- Methode (auch bekannt als return ) und eine Bind- Methode (auch bekannt als flatMap ) angeben . Persönlich bevorzuge ich es, die Einheit als statisch anzugeben, während bind ein Instanzmitglied ist.

Im Fall der Staatsmonade muss die Einheit wie folgt sein:

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

while bind (als Instanzmitglied) ist:

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);
    });
}

Sie bemerken, dass bind einen generischen Typ B einführen muss, da dies der Mechanismus ist, der die Verkettung heterogener Zustandsmonaden ermöglicht und dieser und jeder anderen Monade die bemerkenswerte Fähigkeit verleiht, die Berechnung von Typ zu Typ zu verschieben.

Ich würde hier mit dem Java-Code aufhören. Das komplexe Zeug befindet sich im GitHub-Projekt. Im Vergleich zu früheren Java-Versionen entfernen Lambdas viele geschweifte Klammern, aber die Syntax ist immer noch ziemlich kompliziert.

Nebenbei zeige ich, wie ähnlicher Status-Monadencode in anderen Mainstream-Sprachen geschrieben werden kann. Im Falle der Scala, bind (die in diesem Fall muss aufgerufen werden flatMap ) liest sich wie

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)
})

in der Erwägung, dass die Bindung in JavaScript mein Favorit ist; 100% funktional, schlank und gemein, aber natürlich typlos:

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

<shameless> Ich schneide hier ein paar Ecken ab, aber wenn Sie an den Details interessiert sind, finden Sie sie auf meinem WP-Blog. </ shameless>

Marco Faustinelli
quelle
1
Ich bezweifle nicht, dass Sie eine ernsthafte und nützliche Antwort haben, aber der wichtige Teil davon (wie haben Sie ihn tatsächlich in Java implementiert) ist hinter einem Link verborgen. Links werden im Laufe der Zeit veraltet. Aus diesem Grund sollten Sie die wichtigen Aspekte Ihrer Antwort in die Antwort selbst und nicht in einen Link aufnehmen. Da es sich um Ihre eigene Seite handelt, auf die Sie verlinkt haben, können Sie den wichtigsten Teil davon sicher zusammenfassen und hier in Ihre Antwort aufnehmen.
Erwin Bolwidt
Guter Punkt. Es tut uns leid. Ich werde es vor dem Ende des Tages tun. In der Zwischenzeit bitte nicht abstimmen :-) :-) :-) :-)
Marco Faustinelli
5

Die einzige Möglichkeit, Monaden zu verstehen, besteht darin, eine Reihe von Kombinatorbibliotheken zu schreiben, die resultierende Duplizierung zu bemerken und dann selbst herauszufinden, mit Monaden Sie diese Duplizierung herausrechnen können. Wenn man dies entdeckt, baut jeder eine Intuition für das auf, was eine Monade ist… aber diese Intuition kann man nicht direkt mit jemand anderem kommunizieren - es scheint, dass jeder die gleiche Erfahrung machen muss, um aus einem konkreten Grund auf Monaden zu verallgemeinern Beispiele für Kombinatorbibliotheken. jedoch

Hier habe ich einige Materialien gefunden, um Mondas zu lernen.

Ich hoffe, auch für Sie nützlich zu sein.

Codecommit

james-iry.blogspot

debasishg.blogspot

Morteza Adi
quelle
1
sie alle verbinden sich mit scala? War auf der Suche nach einer Java-Implementierung
NimChimpsky
Ich habe versucht zu erklären, warum eine Java-Implementierung schwierig ist.
Faiz
5

Hier ist die Sache mit Monaden, die schwer zu verstehen ist: Monaden sind ein Muster, kein bestimmter Typ. Monaden sind eine Form, sie sind mehr eine abstrakte Schnittstelle (nicht im Java-Sinne) als eine konkrete Datenstruktur. Infolgedessen ist jedes beispielbasierte Tutorial zur Unvollständigkeit und zum Scheitern verurteilt. [...] Der einzige Weg, Monaden zu verstehen, besteht darin, sie als das zu sehen, was sie sind: ein mathematisches Konstrukt.

Monaden sind keine Metaphern von Daniel Spiewak


Monaden in Java SE 8

Liste Monade

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());
    }
}

Vielleicht Monade

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))));
    }
}

Monade ist ein generisches Muster für die Kapselung verschachtelter Kontrollflüsse. Dh eine Möglichkeit, wiederverwendbare Komponenten aus verschachtelten imperativen Redewendungen zu erstellen.

Es ist wichtig zu verstehen, dass eine Monade nicht nur eine generische Wrapper-Klasse mit einer Flat-Map- Operation ist. Zum Beispiel wird ArrayListmit einer flatMapMethode keine Monade sein. Weil Monadengesetze Nebenwirkungen verbieten.

Monade ist ein Formalismus . Es beschreibt die Struktur, unabhängig von Inhalt oder Bedeutung. Menschen haben Schwierigkeiten, sich auf bedeutungslose (abstrakte) Dinge zu beziehen. Sie kommen also auf Metaphern, die keine Monaden sind.

Siehe auch: Gespräch zwischen Erik Meijer und Gilad Bracha.

user2418306
quelle
Beachten Sie, dass in Java fName + " " + middleName()niemals zurückkehren kann null, Optional.ofNullablewas irreführend ist. Wahrscheinlich wolltest du Optional.ofNullable(middleName()).map(mName -> fName + " " + mName)?
Tagir Valeev
2

Dieser Blog-Beitrag enthält ein schrittweises Beispiel dafür, wie Sie einen Monadentyp (Schnittstelle) in Java implementieren und dann verwenden können, um die Vielleicht-Monade als praktische Anwendung zu definieren.

In diesem Beitrag wird erklärt, dass eine Monade in die Java-Sprache integriert ist, wobei der Punkt hervorgehoben wird, dass Monaden häufiger vorkommen als viele Programmierer denken und dass Codierer sie häufig versehentlich neu erfinden .

Katie J. Ots
quelle
Richtiger Link: blog.tmorris.net/posts/maybe-monad-in-java
Ray Tayek
1

Trotz aller Kontroversen über Optionalbefriedigen, oder nicht, die Monade Gesetze, ich in der Regel wie zu sehen Stream, Optionalund CompletableFuturein der gleichen Weise. In Wahrheit bieten alle ein flatMap()und das ist alles, was mich interessiert, und lassen mich die " geschmackvolle Zusammensetzung der Nebenwirkungen " (zitiert von Erik Meijer) annehmen. Also wir können entsprechende haben Stream, Optionalund CompletableFuturein der folgenden Art und Weise:

In Bezug auf Monaden vereinfache ich es normalerweise nur beim Nachdenken flatMap()(aus dem Kurs " Prinzipien der reaktiven Programmierung " von Erik Meijer):

Eric-Meijer-flatMap

Miguel Gamboa
quelle
0

Ich denke gerne an Monaden, die etwas mathematischer (aber immer noch informeller) sind. Danach werde ich die Beziehung zu einer der Java 8-Monaden CompletableFuture erklären .

Zuallererst ist eine Monade Mein Funktor . Das heißt, es wandelt einen Typ in einen anderen Typ um: Wenn Xes sich um einen Typ handelt (z. B. String), haben wir einen anderen Typ M<X>(z List<String>. B. ). Darüber hinaus, wenn wir eine Transformation / Funktion habenX -> Y von Typen haben, sollten wir außerdem eine Funktion erhalten M<X> -> M<Y>.

Aber es gibt mehr Daten zu einer solchen Monade. Wir haben eine sogenannte Einheit, die X -> M<X>für jeden Typ eine Funktion ist X. Mit anderen Worten, jedes Objekt vonX kann auf natürliche Weise in die Monade eingewickelt werden.

Die charakteristischsten Daten einer Monade sind jedoch das Produkt: eine Funktion M<M<X>> -> M<X>für jeden TypX .

Alle diese Daten sollten einige Axiome wie Funktionalität, Assoziativität und Einheitsgesetze erfüllen, aber ich werde hier nicht ins Detail gehen und es spielt auch keine Rolle für den praktischen Gebrauch.

Wir können nun eine andere Operation für Monaden ableiten, die häufig als äquivalente Definition für Monaden verwendet wird, die Bindungsoperation: Ein Wert / Objekt in M<X>kann mit einer Funktion gebunden werden, um einen X -> M<Y>anderen Wert in zu ergeben M<Y>. Wie erreichen wir das? Nun, zuerst wenden wir Funktionsfunktionalität auf die Funktion an, um eine Funktion zu erhalten M<X> -> M<M<Y>>. Als nächstes wenden wir das monadische Produkt auf das Ziel an, um eine Funktion zu erhalten M<X> -> M<Y>. Jetzt können wir den Wert von einstecken M<X>, um einen Wert in zu erhaltenM<Y> gewünschten . Diese Bindungsoperation wird verwendet, um mehrere monadische Operationen miteinander zu verketten.

Kommen wir nun zum CompletableFuture- Beispiel, d CompletableFuture = M. H. Stellen Sie sich ein Objekt CompletableFuture<MyData>als eine Berechnung vor, die asynchron ausgeführt wird und MyDataals Ergebnis in der Zukunft ein Objekt ergibt . Was sind die monadischen Operationen hier?

  • Funktionalität wird mit der Methode realisiert thenApply: Zuerst wird die Berechnung durchgeführt und sobald das Ergebnis verfügbar ist, wird die Funktion, die gegeben thenApplywird, angewendet, um das Ergebnis in einen anderen Typ umzuwandeln
  • Die monadische Einheit wird mit der Methode realisiert completedFuture: Wie aus der Dokumentation hervorgeht, ist die resultierende Berechnung bereits abgeschlossen und liefert sofort den angegebenen Wert
  • Das monadische Produkt wird nicht durch eine Funktion realisiert, aber die folgende Bindungsoperation ist äquivalent dazu (zusammen mit der Funktionalität) und seine semantische Bedeutung ist einfach die folgende: Bei einer Berechnung des Typs CompletableFuture<CompletableFuture<MyData>>ergibt diese Berechnung asynchron eine andere Berechnung, bei CompletableFuture<MyData>der wiederum einige erhalten werden Wert in MyDataspäter, so dass beide Berechnungen nacheinander durchgeführt werden, ergibt insgesamt eine Berechnung
  • Die resultierende Bindungsoperation wird durch das Verfahren realisiert thenCompose

Wie Sie sehen, können Berechnungen jetzt in einem speziellen Kontext zusammengefasst werden, nämlich der Asynchronität . Die allgemeinen monadischen Strukturen ermöglichen es uns, solche Berechnungen im gegebenen Kontext zu verketten. CompletableFuturewird beispielsweise im Lagom- Framework verwendet, um auf einfache Weise hochasynchrone Anforderungshandler zu erstellen, die transparent durch effiziente Thread-Pools gesichert werden (anstatt jede Anforderung durch einen dedizierten Thread zu behandeln).

Werner Thumann
quelle
0

Ein Diagramm für die "optionale" Monade in Java.

Ihre Aufgabe: Führen Sie Operationen an den "Istwerten" (linke Seite) aus, indem Sie Elemente vom Typ T Vereinigung null in Typ U Vereinigung umwandeln, nullindem Sie die Funktion in der hellblauen Box (die hellblaue Boxfunktion ) verwenden. Hier wird nur ein Kästchen angezeigt, aber möglicherweise befindet sich eine Kette der hellblauen Kästchen (also von Typ U Union null zu Typ V_union nullzu Typ W Union null usw.).

In der Praxis werden Sie sich Sorgen über nullWerte machen , die in der Funktionsanwendungskette angezeigt werden. Hässlich!

Lösung: Wickeln Sie Ihre mit den hellgrünen BoxfunktionenT in eine ein Optional<T>und wechseln Sie zu den "Optionen" (rechte Seite). Transformieren Sie hier Elemente vom Typ in Typ mithilfe der Red-Box-Funktion . In Anlehnung an die Anwendung von Funktionen auf die "Istwerte" können mehrere Red-Box-Funktionen verkettet werden (von Typ zu dann zu usw.). Wechseln Sie am Ende über eine der dunkelgrünen Boxfunktionen von den "Optionen" zu den "Istwerten" zurück .Optional<T>Optional<U>Optional<U>Optional<V>Optional<W>

Keine Sorge nullmehr um Werte. In Bezug auf die Implementierung wird es immer eine geben Optional<U>, die leer sein kann oder nicht. Sie können die Aufrufe an die Red-Box-Funktionen ketten ohne Nullprüfungen .

Der entscheidende Punkt: Die Red-Box-Funktionen werden nicht einzeln und direkt implementiert. Stattdessen werden sie aus den Blue-Box-Funktionen (je nachdem, welche implementiert wurden und verfügbar sind, im Allgemeinen die hellblauen) unter Verwendung der Funktionen mapoder der flatMapFunktionen höherer Ordnung erhalten.

Die grauen Kästchen bieten zusätzliche Supportfunktionen.

Einfache.

Java Optional, wie man es benutzt

David Tonhofer
quelle