2010-07-26 12 views

risposta

9

Potrebbe essere utile prendere in considerazione, per quanto riguarda la notazione do, di cosa si tratta effettivamente buono per. Come sottolinea Travis Brown, in precedenza ho sostenuto l'uso di uno stile di "applicazione di funzione" con Monad s e tipi correlati, ma c'è anche un altro aspetto positivo: Alcune espressioni semplicemente non possono essere scritte in modo pulito nella funzione diretta stile applicativo. Ad esempio, la seguente possibile effettuare rapidamente stile applicativa goffa:

risultati
  • intermedi utilizzati in più sottoespressioni, a diverse profondità di annidamento
  • argomenti della funzione più esterna utilizzati profondamente annidato in subespressioni
  • scomode o incoerenti ordine argomentativo, cioè bisogno di applicare parzialmente una funzione a qualcosa di diverso dal primo argomento
  • Controllo di flusso profondamente incorporato basato su risultati intermedi, con sottoespressioni condivise tra rami
  • Modello di corrispondenza o n risultati intermedi, in particolare nel caso di estrazione di parte di conseguenza, utilizzando tale per ulteriore calcolo, poi ricostruire una versione modificata come risultato successivo

Scrivi funzione come una singola espressione generalmente richiede sia più lambda nidificati o il tipo di sciocchezze offuscanti e assurde che danno a uno stile senza punti un brutto nome. Un blocco do, d'altra parte, fornisce uno zucchero sintattico per un semplice scope annidato di risultati intermedi con il flusso di controllo incorporato.

Normalmente si sarebbe probabilmente estrarre tali sottoespressioni e metterli in una clausola where o qualcosa del genere, ma dal momento che i valori comuni formano una monade con l'applicazione funzione (>>=) --namely il Identity Monade - si potrebbe plausibilmente scrivere un tale funzione in un blocco do, anche se le persone potrebbero guardarti in modo divertente.


Oltre la roba scoping/vincolante, l'altra cosa un blocco do fa per voi è Elide l'operatore che le catene sottoespressioni insieme. Non è troppo difficile immaginare altri casi in cui sarebbe bello avere una notazione per "combinare queste espressioni usando questa funzione all'interno di questo blocco", e quindi lasciare che il compilatore riempia gli spazi vuoti.

Nel caso facile, in cui le espressioni hanno tutte lo stesso tipo, inserirle in un elenco e quindi piegarle funziona bene: creare stringhe in questo modo utilizzando unwords e unlines, ad esempio. Il vantaggio di do è che combina espressioni con struttura comune e tipi compatibili, ma non identici.

Infatti, lo stesso principio generale vale la notazione "staffa linguaggio" dalla carta Applicative: Dove do blocchi utilizzano newlines elidere costruzione monadic, staffe idiom utilizzano giustapposizione elidere applicazione funzione sollevato. Il proc notazione per Arrow è simile, e altri concetti potrebbe essere pulito espressa in tal modo, così, ad esempio:

  • Composizione strutture di dati, ad esempio fondendo set di risultati di qualche tipo, elidendo la funzione di unione
  • Altri linguaggi applicativi funzione, come stile "pipe avanti" argomento della prima, elidendo l'operatore applicazione
  • calcoli paralleli, elidendo la funzione di aggregazione risultato

Anche se non è troppo difficile rendere molti di questi in un singolo tipo o in un'istanza completa Monad, potrebbe essere bello avere un bit di zucchero sintattico unificato ed estensibile per il concetto generale. C'è sicuramente un filo comune che lega tutti questi e altri, ma questo è un argomento molto più ampio non relativo alla sintassi ...

3

Applicative ha (molto più limitato, e più compatto) Idiom staffe, vedere Applicative Programming with Effects, di pagina 4. Conor McBride Strathclyde Haskell Ambiente ha messo in atto questi , Credo.

Non vedo come generalizzare questo tipo di sintassi speciali, ma forse non ci ho pensato abbastanza.

13

mia sensazione è che many Haskell programmers don't love do a tutti, e uno degli argomenti comuni a favore di usare Applicative quando non è necessario il pieno potere di Monad è che i combinatori <$>, <*>, ecc permettono una chiara e concisa stile di codifica.

Anche per il codice monadico, molte persone preferiscono utilizzare =<< in modo esplicito invece della notazione do. camccann 's answer to your previous question about <*> offre un argomento fantastico per questa preferenza.

Tendo a scrivere le mie prime bozze utilizzando do e quindi sostituisco con i combinatori durante la revisione. Questa è solo una questione della mia (in) esperienza e gusto: spesso è più facile per me abbozzare le cose in modo più imperativo (che è più conveniente con do), ma penso che il codice non-do di solito sia più carino.

Per le frecce, d'altra parte, non riesco a immaginare di non utilizzare proc e command do. Le tuple diventano così brutte così rapidamente.

+0

Uomo, mi sento un po 'male - hai superato due volte i upvotes qui e anche collegato a una delle mie risposte precedenti, ma la mia risposta è stata accettata invece ... per quello che vale, sostengo con tutto il cuore questo risposta! –

7

Il do notazione è fondamentalmente un modo di dire "trasformare a lambda come necessario e distribuire >>= tra le righe".

Quando è ovvio quale operatore viene utilizzato per rollare tutto, è bello omettere e sfruttare l'operatore "newline".

Newline programmabile sarebbe un buon modo per accedere alla lista di makings, catene applicative, & c. Per creare elenchi, è necessario anche un "outdent programmabile". In realtà, si può solo prendere i tre bit significativi e falli sovraccaricabile:

  • Begin di do.
  • tra do s.
  • Fine do.

Quindi probabilmente non dovresti chiamarlo più do. Forse dovrebbe essere solo una parentesi.

5

Le parentesi di idioma formano un buon modo di pensare a Applicativi, ma non sono l'unica possibile estensione di sintassi.

Philippa Cowderoy pubblicato una proposta di "Applicative do" notazione per Haskell-bar un po 'indietro con l'osservazione che ogni funzione che sembra un po' come:

foo = do 
    x <- bar 
    y <- baz 
    quux y 1234 x 

dove le variabili vincolate da <- si verificano solo nel l'ultima riga potrebbe essere implementata con Applicative - In realtà ho implementato una macro basata sulla regola della sintassi per questo nello schema, che ho chiamato 'ado'.

Ciò è utile nei casi in cui l'ordine degli effetti applicative differenzia dalla "ordine naturale" e presupponendo l'esistenza di 'ado' in Haskell sarebbe solo desugar a:

foo = (\x y -> quux y 1234 x) <*> bar <*> baz 

Tuttavia, lo scoping lessicale le regole sono un po 'sconcertanti.

2

C'è una generalizzazione di monadi che si adatta alla notazione do - monade parametrizzate. Vedi Beyond Monads di sigfpe. Esempio di utilizzo:

test1' = do put 1 
      x <- get 
      put (show x) 
      y <- get 
      return (x,y) 

Questa è una "monade di stato" che memorizza prima un numero e quindi una stringa.

3

BlazeHtml sta utilizzando do -notation quando in realtà è solo una Monoid (anche se avvolto come Monad poter utilizzare do).

Quindi una notazione simile per Monoid s sarebbe utile lì.

Se si guarda il codice del mio gioco "Defend The King", quindi faccio anche un sacco di mconcat e, come BlazeHtml, trarrebbe vantaggio da una sintassi dall'aspetto piacevole.

Problemi correlati