2016-07-07 6 views
1

Я знаю, что это работает:Haskell --- Использование "пусть" в "делать" синтаксис в GHCI

do name <- getLine; let nameTag = "Hello, my name is " ++ name in putStrLn nameTag 

Как и этот кусок кода при загрузке в GHCI:

hey = do 
    name <- getLine 
    let nameTag = "Hello, my name is " ++ name 
    putStrLn nameTag 

Но это не работает:

do name <- getLine; let nameTag = "Hello, my name is " ++ name; putStrLn nameTag 

дает следующее сообщение об ошибке:

<interactive>:142:82: 
    parse error (possibly incorrect indentation or mismatched brackets) 

Почему это не работает? Могу ли я заставить его работать? Если да, то как?

+1

Отформатируйте свой код. –

+1

Проблема в том, что парсер считает, что структура вашего кода 'let {nameTag = ...; putStrLn nameTag} 'где он ожидает назначение вместо' putStrLn nameTag'. – Bakuriu

ответ

5

Да, вы можете использовать фигурные скобки вокруг Выпускаемое связывания (ей) неоднозначности синтаксического анализа:

do name <- getLine; let { nameTag = "Hello, my name is " ++ name }; putStrLn nameTag 
+0

Спасибо! Я попытался использовать круглые скобки, но это не сработало. В чем принципиальная разница между фигурными скобками и скобками в Haskell? –

+1

@ RafałPłaszczyk Кронштейны предназначены для разграничения подвыражений. Кудрявые скобки предназначены для устранения неоднозначности синтаксиса языка. (О, и синтаксис записи ...) – MathematicalOrchid

+1

@ RafałPłaszczyk Вы, наверное, заметили, что Haskell чувствителен к отступу. В основном, скобки позволяют писать все в одной строке, записывая блоки ('do, let, where, case') на том же уровне отступов, что и' {entry1; entry2; ...} '. Обычно не требуется, кроме GHCi. Во многих случаях достаточно только ';', и скобки могут быть опущены. – chi

4

Чтобы дополнить ответ на McKenna, ошибка может быть объяснена следующим образом: сравнить эти две линии

do name <- getLine; let name1 = "One"; putStrLn name1 
do name <- getLine; let name1 = "One"; name2 = "Two"; putStrLn name1 

У человека читатель может видеть, что они на самом деле означает

do { name <- getLine; let { name1 = "One" } ; putStrLn name1 } 
do { name <- getLine; let { name1 = "One"; name2 = "Two" }; putStrLn name1 } 

но синтаксический анализатор не это умный. Когда анализатор Haskell видит общую часть кода

do name <- getLine; let name1 = "One"; 
            --^-- 

он должен решить, принадлежит ли последний ; на do уровне (как и в первом случае выше), или к let уровня (второй случай). Оказывается, он выбирает let, и позже он не работает.