Haskell 很丑但并不是真的丑
我在网上看到的大多数 Haskell 代码都很丑,但这并不是语言的原因。真正的原因是人们缩进以及命名变量的方式。Haskell 用缩进作为语法的一部分,但不像 Python,Haskell 并不强制缩进宽度一致。这给了你一些格式上的自由,但这也给了没品味的人同样的自由。
拿这个做例子来说(来自 Haskell wikibook):
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
这就只是 10 行简单代码,但仍然又丑又难读。为什么?
缩进总体上就是不一致。他们给这两行用 3 个空格缩进:
doGuessing num = do
putStrLn "Enter your guess:"
但是给这两行用 2 个空格缩进:
if (read guess) < num
then do putStrLn "Too low!"
他们还继承了 SICP 里面那个愚蠢的缩进风格,这使得这里的 doGuessing 那行和 then do 那行相差 1 个空格:
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
putStrLn 就是个很丑的名字,不幸的是它是个标准库函数。这函数名应该得是 printLine 这样的,看着要漂亮多了,也能和 getLine 一致。
这段代码也缺乏一些垂直空行和水平对齐。
解决这些问题后,代码变成了这样:
doGuessing num = do
printLine "Enter your guess:"
guess <- getLine
if (read guess) < num then do
printLine "Too low!"
doGuessing num
else if (read guess) > num then do
printLine "Too high!"
doGuessing num
else
printLine "You Win!"
这只加了 3 行代码(其中 2 行是空行),看起来就好多了。如果你想要“正确”的嵌套,可以这么写,仍然会比原代码好:
doGuessing num = do
printLine "Enter your guess:"
guess <- getLine
if (read guess) < num
then do
printLine "Too low!"
doGuessing num
else if (read guess) > num
then do
printLine "Too high!"
doGuessing num
else
printLine "You Win!"