我试图通过代码的出现来学习 Haskell(我知道,现在已经是这个季节的末了),但我遇到了我不理解的缩进问题,尽管检查了我认为是 haskell.org 上的相关部分或wikibooks。
具体来说,在缩进我的内部辅助函数时,如果我缩进 4 个或更少的空格(不包括主块的 4 个缩进空间),haskell 将发送解析错误,但如果缩进至少 5 个额外空格,则哈斯克尔将起作用。所以我需要将 let ... 至少缩进 9 个空格。然而,将主块缩进 4 个空格而不是 5 个似乎工作正常,我不明白其中的区别。
所以这有效:
solvePart1 :: String -> IO ()
solvePart1 input = do
let parsedInput = map (map read . words) . lines $ input :: [[Int]]
let validateReport report =
let differences = zipWith (-) report (tail report)
in all (\d -> d >= 1 && d <= 3) differences || all (\d -> d <= -1 && d >= -3) differences
let areReportsValid = map validateReport parsedInput
let validReportsCount = sum $ map fromEnum areReportsValid
putStrLn $ "Day 2, Part 1: " ++ show validReportsCount
但这不是:
solvePart1 :: String -> IO ()
solvePart1 input = do
let parsedInput = map (map read . words) . lines $ input :: [[Int]]
let validateReport report =
let differences = zipWith (-) report (tail report)
in all (\d -> d >= 1 && d <= 3) differences || all (\d -> d <= -1 && d >= -3) differences
let areReportsValid = map validateReport parsedInput
let validReportsCount = sum $ map fromEnum areReportsValid
putStrLn $ "Day 2, Part 1: " ++ show validReportsCount
该问题与语法中的 do 与 let ... 无关,因为将内部函数重写为 do 块不会改变问题:仍然需要 5 个空格。
(我使用 vscode 作为编辑器,并使用堆栈进行构建,以防相关)
在某种程度上,它等同于:
solvePart1 input = do
let parsedInput = map (map read . words) . lines $ input :: [[Int]]
对:
solvePart1 input = do
let parsedInput = map (map read . words) . lines $ input :: [[Int]]
该项目需要位于定义范围的标识符开头右侧的一列。所以
let
本身不算数,事实上,例如同样也不起作用:
let x y =
let tmp = y
in tmp
in x 5
如果
let
比 x
更靠右一列,则有效:
let x y =
let tmp = y
in tmp
in x 5
话虽如此,通常您不会在
let
块中使用大量 do
,而是使用没有 do
块的函数,例如:
validateReport :: [Int] -> Bool
validateReport report = all (\d -> d >= 1 && d <= 3) differences || all (\d -> d <= -1 && d >= -3) differences
where
differences = zipWith (-) report (tail report)
solve :: [[Int]] -> Int
solve parsedInput = sum (map fromEnum (map validateReport parsedInput))
然后用以下方法解决:
solvePart1 :: String -> IO ()
solvePart1 input = do
let parsedInput = map (map read . words) . lines $ input :: [[Int]]
putStrLn $ "Day 2, Part 1: " ++ show (solve parsedInput)