一看就懂的 Haskell 教程 - 注释与代码风格

24 阅读4分钟

Haskell 注释支持单行/多行/嵌套三种灵活形式,代码风格以缩进驱动的隐式布局为核心(显式布局为补充),二者均围绕代码可读性、语法简洁性设计,贴合声明式编程「无冗余分隔符」的思想,以下是核心内容+精准示例,直击重点无冗余。

一、注释:单行/多行/嵌套(3种形式,按需使用)

注释内容会被编译器完全忽略,核心优势是支持嵌套(解决C/Java等语言的多行注释嵌套痛点),覆盖简短说明、大段注释、临时代码屏蔽所有场景。

1. 单行注释:-- 注释内容

  • 规则:从--开始到行尾均为注释,行内后续代码无效;
  • 适用:函数功能、类型签名、单行代码的简短说明;
  • 示例
-- 计算两数之和(函数功能说明)
add :: Int -> Int -> Int  -- 类型签名:Int→Int→Int(行尾简短注释)
add a b = a + b

2. 多行/嵌套注释:{- 注释内容 -}

  • 核心规则{-开头、-}结尾,可跨多行,支持无限嵌套(最核心优势);
  • 适用:大段逻辑说明、临时注释掉包含注释的代码块(无需修改原有注释);
  • 示例
{- 多行注释:
  函数核心:纯函数实现两数相加,无副作用
  特性:引用透明,相同输入始终返回相同输出
  {- 嵌套注释:基础示例,无边界条件处理 -}  -- 支持嵌套,编译器正常识别
-}
add a b = a + b

-- 临时屏蔽代码块(即使块内有注释,直接包裹即可)
{-
factorial :: Int -> Int
factorial 0 = 1  -- 基准条件
factorial n = n * factorial (n-1)
-}

3. 注释核心优势

  1. 灵活适配:短注释用--,长注释/屏蔽代码用{- -},无需妥协;
  2. 嵌套友好:解决传统语言多行注释无法嵌套的问题,开发效率高;
  3. 编译器高效:标记明确,编译器快速跳过,不影响编译速度。

二、代码风格:缩进规则(隐式/显式布局,核心是缩进)

Haskell 是将缩进作为语法一部分的语言(非单纯编码规范),缩进直接决定代码块边界,核心分「隐式布局(推荐)」和「显式布局(补充)」,二者可混合使用。

核心前提

行业规范:统一用4个空格缩进,禁止用Tab(避免不同编辑器Tab宽度差异导致语法错误)。

1. 隐式布局(默认/推荐,缩进驱动)

  • 核心规则:以缩进级别区分代码块,是Haskell的默认语法,覆盖99%开发场景;

① 同一代码块的内容,必须保持相同缩进级别

② 缩进更深的代码,属于「内层子块」;

③ 缩进回到原级别,代表「内层子块结束」;

  • 适用场景:函数定义、let/where块、do块、条件判断、模式匹配等所有核心场景;
  • 经典示例(覆盖高频使用场景):
-- 示例1:where块的隐式布局(pi/circ/area缩进一致,同属where块)
circle :: Double -> (Double, Double)  -- 返回(周长,面积)
circle r = (circ, area)
  where  -- where块开始,后续内容缩进4个空格
    pi = 3.14159        -- 4空格,where块一级绑定
    circ = 2 * pi * r   -- 同级别缩进,与pi同级
    area = pi * r * r   -- 同级别缩进,与pi/circ同级

-- 示例2:do块的隐式布局(IO操作,核心看缩进层级)
main :: IO ()
main = do  -- do块开始,后续内容缩进4个空格
  putStrLn "请输入数字:"  -- 4空格,do块一级操作
  numStr <- getLine       -- 同级别缩进,与上一行同级
  let num = read numStr :: Int  -- 内层缩进(8空格),do块的子块
  putStrLn $ "你输入的是:" ++ show num  -- 回到4空格,do块一级操作

-- 示例3:条件判断的隐式布局(then/else分支缩进一致)
ifDemo :: Int -> String
ifDemo x = if x > 0
           then "正数"  -- 缩进4个空格,与else同级
           else "非正数" -- 同级别缩进,与then同级

2. 显式布局(大括号+分号,无缩进依赖)

  • 核心规则:用{}包裹代码块,分号; 分隔块内的多个绑定/表达式,无需依赖缩进,是隐式布局的补充;
  • 适用场景:单行定义多个绑定、代码生成、需要明确块边界的特殊场景;
  • 示例
-- 示例1:let块的显式布局({}包裹,;分隔绑定,单行完成)
explicitLet :: Int -> Int
explicitLet x = let {y = x*2; z = y+3} in y + z  -- 无需缩进,语法合法

-- 示例2:where块的显式布局
explicitWhere :: Int -> Int
explicitWhere x = f x where {f n = n*n; g n = n+1}  -- ;分隔多个函数绑定

3. 混合布局(隐式+显式,适配特殊场景)

隐式布局中可嵌套显式布局,兼顾「代码简洁」和「特殊场景需求」,核心是外层用隐式(缩进),内层特殊逻辑用显式({}+;)

  • 示例
-- do块(隐式)中嵌套显式let块,无需额外缩进,直接定义
mixLayout :: IO ()
mixLayout = do
  putStrLn "混合布局示例"
  let {a = 1; b = 2; c = a+b}  -- 显式let块,;分隔,无需缩进
  putStrLn $ "a+b+c=" ++ show (a+b+c)  -- 回到do块缩进级别

4. 布局设计核心优势

  1. 代码简洁:消除命令式语言大量的{};,聚焦逻辑本身,贴合声明式编程;
  2. 结构清晰:缩进级别=逻辑嵌套级别,代码物理结构与逻辑结构完全一致,易读易维护;
  3. 规范统一:将缩进从「团队规范」提升为「语法规则」,避免风格冲突;
  4. 减少错误:无需担心遗漏{}/;导致的语法错误,开发效率更高。

三、核心总结

注释

  1. 单行短注释用--,行尾/简短说明首选;
  2. 多行注释/屏蔽代码用{- -}支持嵌套是核心优势;
  3. 注释仅对开发者可见,编译器会完全忽略,不影响代码执行。

代码风格

  1. 首选隐式布局,4个空格缩进,缩进级别决定代码块边界;
  2. 特殊场景用显式布局({}+;),无缩进依赖,是隐式布局的补充;
  3. 缩进是Haskell语法一部分,非单纯规范,缩进错误会直接导致编译失败。