Perché Scala indica la composizione monadica come "per la comprensione"?

6

Non sono sicuro che sia una domanda appropriata, ma eccola qui.

So che la notazione di Haskell è abbastanza buona. E mi sono reso conto che la "comprensione" di Scala è in realtà la stessa cosa della notazione in Haskell. Qualcosa che non capisco è perché i designer hanno scelto questo nome? Le parole "for" e "yield" sembrano confondere i programmatori che sono abituati, ad esempio, a Java for loop e Ruby's yield.

Tuttavia non penso che la composizione monadica abbia molto in comune con quelle cose. C'è una ragione particolare per denominare questo zucchero sintattico con tali parole? O è solo perché molte parole chiave sono già state occupate nella lingua, quindi hanno dovuto usare queste parole chiave relativamente gratuite?

    
posta xji 16.01.2016 - 12:27
fonte

2 risposte

13

Penso che tu stia creando una falsa dicotomia qui.

Haskell ha una comprensione monade integrata nella lingua. Una ragione per questo è l'uso delle monadi per l'I / O in stile imperativo. Pertanto, i progettisti di Haskell hanno deciso di farlo apparire come un blocco di codice in un linguaggio generico in stile C, completo di parentesi graffe, punto e virgola e persino return . I compiti sembrano un po 'non-C, ma la freccia sinistra per l'assegnazione è un tipico pseudo-codice imperativo.

Quindi, le interpretazioni di monade in Haskell sono state progettate per sembrare blocchi di codice sequenziali di effetto collaterale imperativi in un linguaggio C / pseudo-codice generico, perché è un caso d'uso importante per loro. Ciò permea anche la progettazione dell'API con la denominazione della funzione return sopra menzionata. Nota che il nome di questa funzione non ha molto senso se lo usi al di fuori della notazione do .

C # ha una comprensione monade integrata nella lingua. Una ragione per questo è l'uso delle monadi per l'interrogazione dei set di dati. Pertanto, i progettisti di C # hanno deciso di farlo sembrare per lo più come SQL o XQuery, completi di FROM , SELECT , WHERE , GROUPBY , ORDERBY , ecc. L'ordine sembra un po 'non SQL ( FROM prima di SELECT ), ma è lo stesso usato da XQuery, in realtà.

Quindi, le interpretazioni di monade in C # sono state progettate per assomigliare a query SQL, perché è un caso d'uso importante per loro. Questo permea anche il design dell'API con la denominazione di ad es. Select per la funzione di trasformazione (anziché map ), SelectMany (invece di flatMap ), Where (invece di select / filter ), ecc. Si noti che i nomi di queste operazioni non ha molto senso se li usi al di fuori della comprensione di una query e, in effetti, puoi persino confonderti attivamente ( Select è ciò che viene solitamente chiamato map , mentre ciò che è solitamente chiamato select è Where ).

Scala ha una comprensione monade costruita nella lingua. Una ragione per questo è l'uso delle monadi per le operazioni di raccolta. Pertanto, i progettisti di Scala hanno deciso di farlo sembrare per lo più come un ciclo for in un linguaggio generico in stile C. I compiti sembrano un po 'non-C, ma la freccia sinistra per l'assegnazione è un tipico pseudo-codice imperativo.

Quindi, le interpretazioni di monade in Scala sono state progettate per apparire come imperative for loop in un linguaggio C / pseudo-codice generico, perché è un caso d'uso importante per loro.

Si noti che sia nel caso di C # che di Scala, la sintassi di comprensione può effettivamente fare più e / o meno di eseguire solo le due operazioni monadiche join e bind (o map e flatMap ). In Scala, una comprensione for senza yield si traduce in foreach , cioè un'imperativa iterazione con effetti collaterali, che in realtà non ha molto a che fare con le monadi. Un yield può avere una guardia ( yield foo if bar ), che si traduce in una chiamata a una chiamata a withFilter , cioè elementi filtranti. C # può fare lo stesso con Where . C # può anche fare aggregazione ( group by ) e ordinamento ( order by ).

In realtà sono più di una generalizzazione e / o fusione di comprensione di monadi e di liste generalizzate a raccolte e monade arbitrarie. Nota che Haskell ha anche entrambi, ma sono elementi diversi , in C # e Scala, sono fusi insieme.

Haskell ha un sacco di storia e ha aperto la strada a molti concetti. Come è tipico dei pionieri, spesso le persone che vengono dopo di loro, scoprono itinerari migliori, più brevi e più sicuri. Forse se Haskell fosse stato progettato con il senno di poi anziché con l'innovazione, avrebbero anche una comprensione generalizzata delle liste per lavorare con più collezioni, e avrebbero fuso le comprensioni monad e le comprensioni generalizzate insieme, chi lo sa? So che ci sono varianti ed estensioni proposte ad Haskell, che aggiungono ad esempio Arrow Comprehensions.

The words "for" and "yield" seem likely to confuse programmers who are used to, for example, Java's for loop and Ruby's yield.

Il primo è intenzionale. È supposto che assomigli a un for loop.

Il secondo è sfortunato. La parola yield ha due significati (in realtà correlati ma non ovviamente così). Uno è il significato usato in concorrenza, coroutine, fibre, discussioni e per la parola chiave yield e il metodo Fibre#yield in Ruby, dove significa che un pezzo di codice fornisce il controllo dell'esecuzione su un altro pezzo di codice. L'altro è il significato di un calcolo che produce un risultato. Questo è il significato che viene utilizzato nei generatori Python, nei generatori C # e, interessantemente anche in Ruby, nel metodo Enumerator::Yielder#yield , ed è l'interpretazione che è intesa per la parola chiave yield in Scala for comprehensions.

    
risposta data 16.01.2016 - 14:04
fonte
3

Non ho molte informazioni sul perché i designer di Scala abbiano fatto quella particolare scelta di parole, ma in F #, l'equivalente locale di "notazione" è chiamato "espressione di calcolo". Il ragionamento alla base di questa scelta di parole è una delle PR e del marketing piuttosto che una ragione tecnica concreta.

Haskell ha una reputazione duramente guadagnata di essere una lingua per accademici, scienziati missilistici e altri strani, e una delle cose che perpetua questa nozione è l'insistenza della sua comunità nell'usare termini derivati dalla teoria dei tipi allo scoperto. Questa è anche una forma di marketing - si potrebbe dire che è una scelta consapevole che lo rende attraente per certi tipi di persone (hipsters di programmazione funzionale) e scoraggiante per gli altri (ad esempio, come gli utenti aziendali).

Per F #, sono andati con "espressioni di calcolo" e "costruttori di espressioni di calcolo" invece di "notazione" e "monade" presumibilmente nel tentativo di non spaventare le persone che sono in grado di cogliere il linguaggio (.NET esistente. programmatori che non hanno uno sfondo di programmazione funzionale).

Immagino che il caso sia simile per Scala. Chiamandolo "per comprensioni", vogliono vendere la funzione a persone che potrebbero non sapere nulla delle monadi, ma che hanno familiarità con la comprensione delle liste in linguaggi come Ruby e Python.

    
risposta data 16.01.2016 - 13:39
fonte