2013-06-24 10 views
28

Mi piacerebbe imparare il concetto, così che sarei in grado di capire e utilizzare librerie come machines.Qual è la differenza concettuale tra Macchine e Conduit (o altre librerie simili)?

Ho provato a seguire Rúnar Bjarnason's talk on machines, ma ci sono troppe informazioni, in pratica solo un gruppo di tipi di dati. Non riesco nemmeno a capire cosa k è in

newtype Machine k o = Step k o (Machine k o) 
data Step k o r = Stop 
       | Yield o r 
       | forall t . Await (t -> r) (k t) r 

o ciò che è t è e perché è quantificato. Oppure, qual è la differenza concettuale tra le librerie conduit e le macchine ?

risposta

44

conduit e pipes sono entrambi molto più maturo rispetto machines, ma - Detto questo - machines sta cercando di prendere una strada diversa rispetto conduit e pipes.

Con machines, sto provando per un'API relativamente semplice in termini di argomenti tipo. Sia conduit e pipes hanno scelto di unificare tutti i loro concetti utilizzando 5-6 diversi argomenti variabili di tipo.

Machines adotta un approccio differente di parametrizzazione una macchina (o Plan) sulla sua "lingua di input", che mette tutta l'onere su un singolo argomento supplementare (o due nel caso di un Plan). Inoltre, scegliendo di parametrizzare la lingua di input in questo modo, si apre la possibilità di utilizzare macchine che possono accettare input (non) deterministicamente da più fonti di input. Il risultato è fondamentalmente solo una monade gratis con un'istruzione extra "emette"!

In cambio di una politica un po 'più rigorosa su come si costruiscono e si utilizzano le macchine, può infine offrire una maggiore sicurezza sulle asintoti del codice risultante.

Detto questo, pipes e conduit hanno avuto un sacco di uso mondo reale e machines è più o meno un parco giochi per me, Rúnar Bjarnason e Paul Chiusano.

Attualmente è adatto per lavorare su input che si intende consumare interamente, ma meno per lavorare con risorse complicate o per l'analisi di quello che si ottiene con le altre due API.

Ora, a proposito di quel quantificatore!

t in realtà esiste quantificato in modo esistenziale. In questo modo possiamo rendere il Monad per le macchine che non si preoccupano della funzionalità del parametro . Questo è importante a causa del modo in cui è implementato lo Source. Se non ho bisogno Source a lavorare, allora potremmo utilizzare la più semplice

data Step k o r = Stop 
       | Yield o r 
       | Await (k r) r 

Ciò avrebbe lo sfortunato effetto collaterale che quando si è andato a comporre una macchina con un Source, che il compilatore non saprebbe quale istanza di Functor scegliere e nuoteresti in annotazioni di tipo non necessarie.

La quantificazione esistenziale è un trucco che ho rilevato quando si lavora sul pacchetto kan-extensions. È una generalizzazione di uno dei tipi Yoneda da lì.

+1

Grazie, potresti approfondire un po 'su 'k'? Perché 'Await' consiste di' k r', in particolare, perché 'k :: * -> *' e parametrizzato da 'r'? Ho provato ad esaminare 'Tee',' Wye' e 'Is' per vedere alcuni esempi di' 'k diversi, ma sono ancora lontano dalla comprensione. –

+4

'k a' è il tipo di una richiesta che stai facendo di qualunque cosa stia alimentando i tuoi dati. 'A' rappresenta il risultato della richiesta. 'Await' ha due argomenti:" La richiesta con cosa fare se la richiesta riesce "e" cosa fare a un errore ". Per un singolo input puoi usare k = (->) i' in modo che 'Machine ((->) i)' abbia una funzione da '(i -> r)' a cui puoi fornire l'input. Con 'Tee' si finisce con una delle due funzioni in modo da poter bloccare su entrambi gli input separatamente. 'Wye' consente di bloccare su uno o entrambi gli input contemporaneamente. 'Is' è appena usato come' (->) 'sopra. –

+1

Un'altra domanda, perché ci sono 'Plan's e' Machine's? Perché la distinzione? –

Problemi correlati