2016-03-19 13 views
15

Ich habe Probleme mit dem Verständnis der Unit-Funktion in JavaScript. Vor allem, weil die Sache, die mich dazu brachte, Monaden zu "bekommen" (oder zumindest dachte ich), das Promise-Objekt war, und wie then immer eine neue Promise zurückgibt, egal welche Funktion du an then übergibst, was meines Wissens bind entspricht oder >>= in Haskell. Das macht für mich durchaus Sinn, denn es stellt sicher, dass alle Ihre Funktionen sozusagen im "Monaden-Universum" ausgeführt werden.JS Monad Unit-Funktion

Was mich stolpert, ist der Vortrag von Douglas Crockford über Monaden und Gonaden. In seiner Implementierung gibt bind direkt das Ergebnis der Transformationsfunktion zurück, ohne zu überprüfen, ob das Ergebnis selbst eine Monade ist. Dies kollidiert mit der then Methode von Promises, da then IMMER eine neue Promise zurückgibt.

Ein Gedanke war die Aufzugsmethode. Seine Implementierung stellt sicher, dass "Lift" immer eine Monade zurückgibt, und vielleicht wurde then auf Promise gehoben. Dies würde jedoch bedeuten, dass then !== bind, und dass Promise irgendwo eine interne Bindung hat.

Meine Intuition ist, dass es mindestens eine Art von Typprüfung in der Bindefunktion geben sollte, die das Ergebnis der Transformation überprüft und ermöglicht, dass eine resultierende Monade durchgelassen wird, aber Nicht-Monaden abfängt und diese weitergibt Einheit wieder, wie 'Lift' tut.

* EDIT
Auch ich habe den Eindruck, dass then-bind, flatMap, >>= gleichwertig ist, weil es die Fähigkeit, andere Monaden auszupacken, darunter verschiedene, und diejenigen von seiner eigenen Art. Bei der Suche nach einigen Kategorientheorie-Referenzen in JavaScript wurde flatMap verwendet, um eine Gruppe von verschachtelten Arrays abzubilden und sie dann um eine Dimension zu reduzieren. Das passt dazu, wie then auf andere Versprechen wartet, die Sie ihm geben. Aber scheint nicht mit der oben genannten ursprünglichen Implementierung übereinzustimmen. Ich fühle mich verloren.

Kann jemand mit mehr Erfahrung FP etwas Licht auf das, was ich vermisse, oder bin ich einfach zu viel los, und müssen von Anfang an beginnen?

Einige Codebeispiele ...

// Crockford's 'bind' 
monad.bind = function(transform) { 
    // value was passed in through the unit constructor 
    return transform(value); 
} 

Mein Problem Bereich

// Set the 'isMonad' prop to be true, for all 
// monads made with the MONAD macroid 
monad.isMonad = true; 

// shouldn't this ALWAYS return a monad? 
monad.bind = function(transform) { 
    var res = transform(value); 
    return (res && res.isMonad) ? res : unit(res); 
} 

HINWEIS Ich weiß, ich bin mit der Endfassung seiner Umsetzung nicht vollständig, ich bin nur insbesondere auf die bind-Methode fokussieren.

Die vollständige Umsetzung kann bei

https://github.com/douglascrockford/monad/blob/master/monad.js

aktualisieren

Nachdem ich etwas mehr Forschung gefunden werden, wird >>= keine Monade Instanz zurückzukehren erforderlich. Bergis Kommentar wirft ein Licht darauf, wie Promise.prototype.then überladen ist und als eine andere Funktion fungiert, je nachdem, was Sie damit lösen.

Viele Dinge begannen zu klicken, als ich einen Schritt zurücktrat und mir ansah, wie Monaden sich von normalen Funktoren unterscheiden. Die Details sind immer noch etwas verschwommen, aber ich denke, ich bekomme das große Bild.

Ein paar gute Referenzen, die klar den Dunst half,

Dieser ist für einen umfassenden Überblick empfehlen, in menschlichen Worten
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Lassen Sie sich nicht die Bilder täuschen, dieses war wie Gold für mich. Nicht in JavaScript, aber immer noch sehr informativ über die allgemeinen Konzepte.

Auch diese YouTube-Serie auf Kategorie Theory in JavaScript
https://www.youtube.com/watch?v=-FkgOHvNAU8&list=PLwuUlC2HlHGe7vmItFmrdBLn6p0AS8ALX&index=1

Diese YouTube-Serie Online 'Fun Fun Function' ist wunderbar, ist der Gastgeber einer der besten Lehrer, die ich gefunden habe angerufen. Dieses Video handelt von Monaden und wurde von MrE vorgeschlagen.
Sehr empfehlenswert !.

https://www.youtube.com/watch?v=9QveBbn7t_c&app=desktop

Diese beiden Referenzen hat Wunder für mich speziell. Hoffnung, die auch allen anderen hilft.

+14

Ich empfehle dringend, ignorieren Sie diese Crockford Talk/Code. Ihr Verständnis von Versprechen ist vernünftig. Du solltest einen * guten * Hinweis darauf finden, dass du Crockfords Rede verwirrend findest, weil er verwirrt ist. –

+3

'dann' ist eine schreckliche Umsetzung einer Monade. Es mischt 'bind' /' chain'/'flatMap'/wie immer man es mit einer normalen' map' bezeichnet, und es akzeptiert auch alle thenables als Rückgabewerte. In Haskell benötigen Sie "isMonad" absolut nicht, da der Compiler bereits überprüft, dass die übergebene Funktion den richtigen Rückgabetyp hat. – Bergi

+4

Fügen Sie eine weitere Empfehlung für "ignorieren Crockford" hinzu. – naomik

Antwort

1

ich nicht ganz bekommt, was Ihre Frage ist, aber ich würde so etwas annehmen: Was ist die korrekte Definition einer Monade ist

und es ist zwei Methoden in Bezug auf JS?

In Haskell Bedingungen (von https://en.wikibooks.org/wiki/Haskell/Understanding_monads genommen), es ist ganz einfach:

return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 

    (>>) :: m a -> m b -> m b 

Für JavaScript Begriffe, suchen Sie nicht weiter, ist die kurze und einfache Antwort hier https://github.com/fantasyland/fantasy-land#monad zusammen mit anderen verbunden FP-Definitionen.

Ein paar Worte über die Methoden:

  1. Eine Sache ist unit (return in Haskell) muss eine Monade produzieren (nicht genau Monade, aber für Zwecke der Beweisführung ...), da es wie Ein Konstruktor, der einen Wert in den Container einfügt. Array.of() ist ein Beispiel, jQuery() ist ein anderes und natürlich auch new Promise().

    In der Fantasy Land Spezifikation ist dies die of() Funktion/Methode.

  2. Die zweite wichtig ist nur, weil Haskell eine Definition von monadisch verwendet mit unit und bind während andere (fmap, join) werden, um sie zu entnehmen bilden.

    Die Haskellsbind gestattet chain im Fantasy Land Spezifikation weil bind auf Function.prototype in JavaScript trotzt, so jemand dachte chain nahe genug wäre.

    Und der Grund, warum bind heißt chain eine Monade des gleichen Typs zurückgeben „muss“ ist wegen (>>=) :: m a -> (a -> m b) -> m b. Kurz gesagt, die Haskellbind Funktion muss nur eine Funktion akzeptieren, die eine Monade zurückgibt (dieser Teil a -> m b), so dass Sie das Ergebnis davon erhalten.

  3. Die Haskellsthen

    ist eine bloße Bequemlichkeit

    und

    Sequenzen zwei monadischen Aktionen, wenn die zweite Aktion das Ergebnis des ersten nicht beteiligt ist, was für Monaden wie IO üblich ist.

In der Praxis:

  1. Es kann Sie in JS verdrießen, da es keine strenge Typdurchsetzung ist, dass Sie immer die Regeln nicht folgen und zurück, was Sie von einem Promise wollen zum Beispiel, wodurch die .then() Kette des Versprechens (der Versprechen) gebrochen wird.

  2. Einige Monaden wie jQuery haben "aufgehoben" -Funktionen als Methoden, die immer jQuery, d. H. Vom gleichen Typ, zurückgeben und somit die Fähigkeit zur Verkettung "schützen".