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.