Во время просмотра https://wiki.haskell.org/IO_inside я столкнулся со следующим комментарием и кодом...
"Кроме того, правила макета Haskell позволяют использовать следующий макет:
main = do a <- readLn if (a>=0) then return () else do print "a is negative" ...
который может быть полезен для выхода из середины длинного заявления do.
В дальнейшем я буду использовать символ C * для ссылки на приведенный выше код.
Я предполагаю, что намерение C * читать в числе, а затем:
(i) Если это неотрицательно, ничего не делайте.
(ii) Если он отрицательный, отобразите вывод, указав, что он есть.
Моя первоначальная реакция заключалась в том, чтобы думать, что C * не будет правильно анализировать или не будет вести себя так, как ожидалось.
Я думал, что Layout будет вставлять пустой набор фигурных скобок и точку с запятой сразу после второго "do", потому что "print" lexeme не имеет отступов больше, чем уровень отступов текущего контекста макета, установленного "a" в "a < - readLn".
То есть, мое предсказание для нечувствительного к макету кода (далее называемого C), сгенерированного макетом, будет выглядеть примерно так:
main = do {
a <- readLn;
if (a>=0) then return ()
else do {};
print "a is negative"
...
}
Что я думал, что это так, было основано на следующем предложении, содержащемся в разделе 2.7 ( "Лексическая структура": "Макет" ) части 1 отчета о языке Haskell 2010 (https://www.haskell.org/onlinereport/haskell2010/haskellpa1.html):
"Если отступ непересекающейся лексемы сразу после того, где, пусть, do или из меньше или равно текущему уровню отступа, вместо того, чтобы начинать макет, вставляется пустой список" {} ", и обработка компоновки происходит для текущего уровня (т.е. вставка точки с запятой или замыкания).
Более подробный отчет о правилах макета приведен в разделе 10.3 ( "Ссылка на синтаксис": "Макет" ) части 1 (указанный выше URL) отчета о языке Haskell 2010.
При чтении этой более подробной учетной записи, я чувствовал себя уверенным, что мое предсказание для нечувствительного к макетам кода, сгенерированного макетом (то есть C '), было правильным.
Однако, к моему удивлению, когда я попробовал исходный код, описанный выше (т.е. C *) в GHCi, он работал (правильно разбирался и вел себя так, как ожидалось).
Вопросы...
-
Является ли приведенное выше предложение (из раздела 2.7) точным?
-
Является ли подробная информация о правилах макета, упомянутых выше (из раздела 10.3) точными?
-
Каковы недостатки в рассуждениях, которые я использовал для получения моего предсказания для нечувствительного к макетам кода (то есть C '), сгенерированного макетом для исходного кода C *?
-
Что представляет собой нечувствительный к макету код, созданный макетом для исходного кода, описанного выше (т.е. для C *), и каковы правила/принципы, которые его объясняют?
-
В общем, есть ли способ, чтобы я мог видеть нечувствительный к макету код, созданный макетом? Если да, то что это (пожалуйста, подробно или объясните технику на уровне, подходящем для кого-то нового для Haskell, как и я)?