2011-11-05 9 views
24

Come sto imparando Haskell mi rendo conto che do notazione è lo zucchero solo syntatic:Dezuccheraggio do-notazione per Monadi

a = do x <- [3..4] 
     [1..2] 
     return (x, 42) 

traduce in

a = [3..4] >>= (\x -> [1..2] >>= (\_ -> return (x, 42))) 

mi rendo conto che io probabilmente usa la notazione, ma mi piacerebbe capire che cosa sta succedendo nella traduzione. Quindi, puramente per ragioni pedagogiche, c'è un modo per ghc/ghci di darmi le corrispondenti istruzioni di binding per una monade abbastanza complessa scritta in do notazione?

Modifica. Si scopre lambdabot su #haskell può fare questo:

<Guest61347> @undo do x <- [3..4] ; [1..2] ; return (x, 42) 
<lambdabot> [3 .. 4] >>= \ x -> [1 .. 2] >> return (x, 42) 

Ecco il codice sorgente del Undo plugin.

+3

in realtà 'm >> = (\ _ -> k)' è 'm >> k' –

+7

Lambdabot ha un plugin" annulla "che desugars notazione –

+1

Sto solo imparando e sento che questo è la chiave per capire veramente i dettagli di una particolare istanza - sono tutti scritti in termini di >> = –

risposta

18

È possibile chiedere l'output del desugarer di GHC, tuttavia questo verrà anche desugar molte altre sintassi.

In primo luogo, metteremo il codice in un modulo Foo.hs:

module Foo where 

a = do x <- [3..4] 
     [1..2] 
     return (x, 42) 

Avanti, ti chiederemo GHC compilarlo e l'output il risultato dopo la fase di Dezuccheraggio:

$ ghc -c Foo.hs -ddump-ds 

L'output potrebbe sembrare piuttosto disordinato, perché è una variante di Haskell chiamata Core usata come linguaggio intermedio di GHC. Tuttavia, non è troppo difficile da leggere dopo esserti abituato. Nel mezzo di alcune altre definizioni troviamo vostra:

Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)] 
LclIdX 
[] 
Foo.a = 
    >>=_agg 
    @ GHC.Integer.Type.Integer 
    @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
    (enumFromTo_ag7 
     (GHC.Integer.smallInteger 3) (GHC.Integer.smallInteger 4)) 
    (\ (x_adf :: GHC.Integer.Type.Integer) -> 
     >>_agn 
     @ GHC.Integer.Type.Integer 
     @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
     (enumFromTo_ags 
      (GHC.Integer.smallInteger 1) (GHC.Integer.smallInteger 2)) 
     (return_aki 
      @ (GHC.Integer.Type.Integer, GHC.Integer.Type.Integer) 
      (x_adf, GHC.Integer.smallInteger 42))) 

Nucleo non è troppo bella, ma essere in grado di leggere che è molto utile quando si lavora con GHC, come si può leggere il dump dopo fasi successive per vedere come GHC sta ottimizzando il tuo codice.

Se togliamo le _xyz suffissi aggiunti dal renamer, così come le applicazioni di tipo @ Xyz e le chiamate a GHC.Integer.smallInteger, e rendere di nuovo l'infisso operatori, si è lasciato con qualcosa di simile:

Foo.a :: [(GHC.Integer.Type.Integer, GHC.Integer.Type.Integer)] 
Foo.a = enumFromTo 3 4 >>= \x -> enumFromTo 1 2 >> return (x, 42) 
+4

Che pone la domanda ... c'è qualcosa là fuori che rimuoverà automaticamente i suffissi _xyz, tipo applic azioni, chiama GHC.Integer.smallInteger e riattiva gli operatori? – hugomg

+1

@missingno: nessuno di cui sono a conoscenza. Tuttavia, ci sono librerie disponibili per lavorare con Haskell o Core su Hackage, quindi non dovrebbe essere troppo difficile per hackerare qualcosa insieme se lo vuoi abbastanza male. – hammar

+2

Il problema è che, quando hai scritto il codice per farlo, non ne hai più bisogno. –

Problemi correlati