2016-03-19 22 views
15

Non riesco a capire la funzione dell'unità in JavaScript. Soprattutto perché la cosa che mi ha fatto ottenere "monade" (o almeno pensavo) era l'oggetto Promise, e come then restituisce sempre una nuova Promessa, indipendentemente da quale funzione si passi a then, che, a mia conoscenza, equivale a bind o >>= in haskell. Questo ha senso per me, perché garantisce che tutte le tue funzioni siano eseguite nell'universo monad, per così dire.JS Funzione unità Monad

Quello che mi incuriosisce è il discorso di Monads and Gonads di Douglas Crockford. Nella sua implementazione, bind restituisce direttamente il risultato della funzione di trasformazione, senza verificare se il risultato stesso, è una monade. Questo si scontra con il metodo then di Promises, poiché then SEMPRE restituisce una nuova promessa.

Un pensiero era il metodo di sollevamento. La sua implementazione assicura che "lift" restituisca sempre una monade, e forse then è stato revocato a Promise. Tuttavia, ciò significherebbe che then !== bind e che Promise ha un vincolo interno da qualche parte.

La mia intuizione è che ci dovrebbe essere almeno una sorta di controllo di tipo nella funzione di bind che controlla il risultato della trasformazione, e permette che una monade risultante venga lasciata passare, ma intercetterà le non-monade e le passerà attraverso unità di nuovo, come fa 'lift'.

* EDIT
Inoltre, sono sotto l'impressione che then equivale a bind, flatMap, >>= perché ha la capacità di scartare altre monadi, compresi quelli e quelli delle essa la propria tipo diverso. Durante l'analisi di alcuni riferimenti di teoria delle categorie in JavaScript, è stato utilizzato flatMap per eseguire il mapping su una serie di matrici annidate e quindi appiattirle di una dimensione. Questo si adatta a come then attenderà altre promesse che gli dai. Ma non sembra corrispondere con l'implementazione originale di cui sopra. Mi sento perso.

Qualcuno con più esperienza FP può far luce su quello che mi manca, o sono semplicemente troppo fuori, e devo ricominciare dall'inizio?

Alcuni esempi di codice ...

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

La mia area guai

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

NOTA So che non sto usando la versione finale della sua piena attuazione, io sono solo concentrandosi in particolare sul metodo bind.

La piena attuazione può essere trovato alla

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

Aggiornamento

Dopo aver fatto qualche ricerca, >>= non è tenuto a restituire un'istanza Monade. Il commento di Bergi fa luce su come Promise.prototype.then è sovraccarico e agisce come una funzione diversa a seconda di come lo risolvi.

Inoltre, un sacco di cose hanno iniziato a fare clic quando ho fatto un passo indietro e ho osservato come i Monad sono diversi dai normali funtori. I dettagli sono ancora un po 'confusi, ma penso di avere una visione d'insieme.

Poche buone referenze che hanno contribuito a cancellare la foschia,

questo è vivamente per una panoramica di alto livello, in parole umane
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Non lasciate che le immagini ingannare, questo era come oro per me. Non in JavaScript, ma ancora molto informativo sui concetti generali.

Inoltre, questa serie di YouTube sulla teoria Categoria in JavaScript
https://www.youtube.com/watch?v=-FkgOHvNAU8&list=PLwuUlC2HlHGe7vmItFmrdBLn6p0AS8ALX&index=1

Questa serie di YouTube chiamata 'Funzione Fun Fun' è meraviglioso, l'ospite è uno dei migliori insegnanti che ho trovato on-line. Questo video riguarda le monadi ed è stato suggerito da MrE.
Altamente raccomandato !.

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

Questi due riferimenti specificamente fatto miracoli per me. Spero che aiuti anche tutti gli altri.

+14

Si consiglia vivamente di ignorare questo talk/codice di Crockford. La tua comprensione delle promesse è ragionevole. Dovresti trovarlo un indicatore * buono * che trovi le parole di Crockford confuse perché è confuso. –

+3

'then' è un'implementazione orribile di una monade. Mescola 'bind' /' chain'/'flatMap'/qualsiasi cosa tu lo chiami con una normale' map', e accetta anche qualsiasi tema come valore di ritorno. In Haskell, non hai assolutamente bisogno di 'isMonad', perché il compilatore già controlla che la funzione che hai passato abbia il tipo di ritorno corretto. – Bergi

+4

Aggiungi un altro consiglio per "ignora Crockford". – naomik

risposta

1

non ho ben capito che cosa la vostra domanda è, ma mi piacerebbe pensare qualcosa di simile:

qual è la corretta definizione di Monade ed è due metodi in termini di JS?

In Haskell termini (prese da https://en.wikibooks.org/wiki/Haskell/Understanding_monads), è semplice:

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

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

Per JavaScript termini, non cercate oltre, la risposta breve e semplice è qui https://github.com/fantasyland/fantasy-land#monad insieme ad altri in contatto Definizioni FP.

Poche parole sui metodi:

  1. Una cosa è unit (return in Haskell) deve produrre una monade (non precisamente monade, ma per amor di discussione ...), in quanto è come un costruttore che inserisce un valore all'interno del contenitore. Array.of() è un esempio, jQuery() è un altro e, naturalmente, new Promise().

    Nella Fantasy Land Specification questa è la funzione/metodo of().

  2. Il secondo è importante solo perché Haskell utilizza una definizione di Monade avente unit e bind mentre altri (fmap, join) sono desunti loro forma.

    Il Haskell delbind si chiama chain nel Fantasy Land Specification perché bind è sfidato sul Function.prototype in JavaScript, così qualcuno ha pensato chain sarebbe abbastanza vicino.

    E la ragione per cui bind cioè chain "must" ritorno una monade dello stesso tipo è a causa di (>>=) :: m a -> (a -> m b) -> m b. In breve, la funzione di Haskellbind deve accettare solo una funzione che restituisce una monade (questa parte a -> m b), in modo da ottenere il risultato.

  3. Il Haskell delthen

    è una mera convenienza

    e

    sequenze due azioni monadici quando la seconda azione non coinvolgono il risultato della prima, che è comune per le monadi come IO.

In pratica:

  1. Può infastidire voi in JS, poiché non v'è nessun tipo rigorosa applicazione, che è sempre possibile non seguire le regole e tornare quello che vuoi da un Promise , ad esempio, rompendo così la catena .then() di dette promesse.

  2. Alcune monade come jQuery hanno funzioni "sollevate" come metodi che restituiscono sempre jQuery, cioè dello stesso tipo, in modo da "proteggere" la capacità di concatenare.