Haskell, “где” добавление отступа: почему это должно быть расположено с отступом мимо идентификатора?

Этот код:

import Data.Char (digitToInt)

myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
  | x == '-'  = -1 * myInt xs
  | otherwise = foldl convert 0 (x:xs)
  where convert acc x
        | x `elem` ['0'..'9'] = 10 * acc + digitToInt x
        | otherwise           = error ("bad input: not an int - " ++ [x])

Сбои:

Вводная часть>: l safeListFs.hs
[1 из 1] Компиляция Основного (safeListFs.hs, интерпретируемый)

safeListFs.hs:9:8: ошибка анализа (возможно неправильное добавление отступа)
Неудавшийся, загруженные модули:ничего.

Но эта версия:

import Data.Char (digitToInt)

myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
  | x == '-'  = -1 * myInt xs
  | otherwise = foldl convert 0 (x:xs)
  where convert acc x
          | x `elem` ['0'..'9'] = 10 * acc + digitToInt x
          | otherwise           = error ("bad input: not an int - " ++ [x])

в порядке:

Вводная часть>: l safeListFs.hs
[1 из 1] Компиляция Основного (safeListFs.hs, интерпретируемый)
Хорошо, загруженные модули: Основной.

Я не могу выяснить, почему те два последних отступа имеют значение.

22
задан Micha Wiedenmann 1 April 2019 в 12:38
поделиться

3 ответа

В основном, Haskell отмечает столбец, в котором стоит первый непробельный символ после , где появляется (в данном случае c из convert ) и обрабатывает следующие строки, начинающиеся в этом столбце, как новые определения внутри , где .

Строка, которая продолжает определение предыдущей строки (например, ваши | охранники), должна иметь отступ справа от первого непробельного символа ( c в вашем коде).

Строка с отступом слева от c будет находиться за пределами , где (например, начало вашей следующей функции верхнего уровня).

Это столбец первого символа после , где имеет решающее значение, даже если он находится в новой строке:

  where
    convert acc x
      | ...
    anotherFunction x y

    ^ 
31
ответ дан 29 November 2019 в 04:15
поделиться

Вложенный контекст должен иметь больший отступ, чем включающий контекст (n> m). В противном случае L не работает, и компилятор должен указать ошибку макета.

Из http://www.haskell.org/onlinereport/syntax-iso.html .

Это тоже не сработает:

import Data.Char (digitToInt)

myInt :: String -> Int
myInt [] = error "bad input: empty string"
myInt (x:xs)
| x == '-'  = -1 * myInt xs
| otherwise = foldl convert 0 (x:xs)
where convert acc x
        | x `elem` ['0'..'9'] = 10 * acc + digitToInt x
        | otherwise           = error ("bad input: not an int - " ++ [x])

Я не умею объяснять. После ключевого слова where есть новый контекст, потому что вы можете указать в нем более одной функции - помните, что ваша программа начинается с неявного модуля Main, где , поэтому я считаю логичным потребовать Тело функции должно быть с отступом, как и на уровне модуля (компилятор ожидает, что другой идентификатор в столбцах M и N, а тела объявлений будут иметь дополнительный отступ).

fun = ...
^ where fun' = ...
M       ^
        N
        fun'' = ...
fun2 = ...
13
ответ дан 29 November 2019 в 04:15
поделиться

Потому что вы всегда должны делать отступ в определениях функций. (В вашем случае все начинается с одного столбца в ], где считаются "одноуровневым" определением).

6
ответ дан 29 November 2019 в 04:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: