2014-01-28 4 views
8

In Haskell können SieLassen Bindungen in Do-Notation ohne Layout "in"?

main = do 
    let x = 5 
    print x 

sagen, und dies wird nicht kompilieren:

main = do 
    let x = 5 
    in print x 

Aber wenn ich explizites Layout verwenden, dies nicht kompiliert:

main = do { 
    let x = 5; 
    print x; 
    } 

aber das funktioniert :

Bin ich richtig? Gibt es einen Ort, an dem ich mehr über explizites Layout lesen und Notation machen und lassen kann? Section 3.14 of the Haskell 98 report scheint mir zu behaupten, dass mein drittes Beispiel funktionieren sollte, wie es sagt, ich

do { let DECLS; stmts } 

schreiben kann und es übersetzt

let DECLS in do { stmts } 
+4

Ich erwarte, dass das Semikolon nach '5' in Ihrem dritten Beispiel als Teil des' let's Blocks geparst wird, nicht des 'do's Blocks. Aber ich habe mich nicht genau genug umgesehen, um sicher zu sein. Vielleicht gefällt Ihnen auch der Abschnitt des Berichts über die Übersetzung von impliziten zu expliziten Blöcken. –

+3

@DanielWagner Du bist auf etwas da; es kompiliert, wenn ich "let {x = 5}" mache –

+2

Ja, das Problem hier kommt von der Mischung der Verwendung von Layout im inneren Let mit den expliziten Klammern und Semikola in der äußeren tun. Wie Daniel sagt, wird das '' 'als Teil der Deklarationen des' let' betrachtet und kann nicht mehr dazu verwendet werden, die Deklarationen im 'do' zu trennen. Ich denke 'do {let {x = 5}; ... ist in der Tat der beste Weg, das Problem zu "beheben". Eine andere Möglichkeit besteht darin, das ';' nach 'x = 5 'an einer Stelle zu platzieren, an der es nicht als Teil des' let'-Layouts interpretiert werden kann, beispielsweise am Anfang der nächsten Zeile, links von 'print x '. – kosmikus

Antwort

2

Die normative Antwort auf Ihre Frage in der Haskell Berichts zu finden Beschreibung der layout rule.

Kurz gesagt, müssen Sie ein Semikolon zwischen Ihrem Let-Block und der nächsten Anweisung des Do-Blocks platzieren. Dieses Semikolon muss außerhalb des Blockes liegen. Wenn Sie nicht Nutzung Layout für die let Block tun , das ist einfach nur sagen:

let {x = 5}; 

Wenn Sie jedoch Verwendung Layout für die let Block tun , dann besteht der einzige Weg, um den let Block schließen ist, eine Zeile in einer Spalte vor der Spalte von x zu beginnen. Das heißt also, dass Sie so etwas schreiben müßten:

main = do { 
    let x = 5 
    ; print x; 
} 

Oh, und für Ihr anderes Beispiel wieder mit Layout ein Semikolon vor den in eingefügt wird immer, so dass Ihr Code desugars zu:

main = do { 
    let {x = 5 
    }; 
    in print x 
} 
Verwandte Themen