2014-01-28 1 views
8

В Haskell можно сказатьПусть привязки в обозначении без макета требуют «в»?

main = do 
    let x = 5 
    print x 

и это не будет компилироваться:

main = do 
    let x = 5 
    in print x 

Но если я использую явное расположение, это не компилируется:

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

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

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

Я прав? Есть ли где-нибудь, где я могу больше узнать о явном макете и сделать и обозначить нотацию? Section 3.14 of the Haskell 98 report мне кажется, предположить, что мой третий пример должен работать, так как он говорит, что я могу написать

do { let DECLS; stmts } 

и переводит

let DECLS in do { stmts } 
+4

Я ожидаю, что точка с запятой после '5' в вашем третьем примере анализируется как часть блока' let', а не блока 'do'. Но я не смотрел достаточно внимательно, чтобы быть уверенным. Вам также может понравиться раздел отчета о переводе от неявных к явным блокам. –

+3

@ Даниэль Вагнер, вы на что-то там; он компилируется, если я делаю «let {x = 5};» –

+2

Да, проблема здесь связана с смешиванием использования макета во внутренней let с явными скобками и точками с запятой во внешнем do. Как говорит Даниил, ';' рассматривается как часть деклараций 'let', а затем не может использоваться для разделения объявлений в' do'. Я думаю: '{{{x = 5}; ... 'действительно лучший способ« исправить »проблему. Другой вариант - поместить ';' после 'x = 5' в место, где он не может быть интерпретирован как часть' let'-layout, например, в начале следующей строки, слева от 'print x '. – kosmikus

ответ

2

Нормативный ответ на ваш вопрос может быть найден в Haskell отчета описание layout rule.

Вкратце, вам нужно поместить точку с запятой между блоком let и следующей операцией блока do. Эта точка с запятой должна лежать вне блока let. Если вы сделать не использовать макет для Выпускаемого блока, который легко, просто сказать:

let {x = 5}; 

Однако, если вы сделать использовать макет для Выпускаемого блока, то единственным способом закрыть Выпускаемый блок - начать строку в столбце перед столбцом x. Так это означает, что вы должны были бы написать что-то вроде этого:

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

О, и для другого примера, снова макете точка с запятой становится вставленным перед in, так что ваш кодом desugars на:

main = do { 
    let {x = 5 
    }; 
    in print x 
} 
Смежные вопросы