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ì.
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. –
'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. –
Un'altra domanda, perché ci sono 'Plan's e' Machine's? Perché la distinzione? –