表达式#

  • 其他语言中的控制语句在 Haskell 中大多以表达式的形式存在;

let表达式#

let <pattern> = <expression>
    ...
in  <expression>
  • let表达式:和where语句类似,let表达式可将表达式绑定至指定名字;

  • 语法格式:

    • let关键字引导所有绑定;

    • 分行书写时一行书写一个绑定,单行书写时,多个绑定用分号;分隔;

      res = let a = 100; b = 200; c = 300 in a * b * c -- 6000000
      
    • let守卫语法

      • let关键词下可使用守卫语法,绑定条件成立的值;

        let <variable>
            | <condition> = <result>
            ...
            | otherwise   = <result>
        in  <expression>
        
        • 当条件成立时,将结果与变量绑定;
        • 不成立则继续向下匹配;
      • 该语法与嵌套的if表达式效果相同;

        let a = if <condition>
              then <result>
              else if <condition>
                  then <result>
                  else <result>
        
    • in关键字定义作用域;

  • 作用域:let表达式的作用域只限于in关键字后的表达式;

  • 绑定:

    • where语句,支持模式匹配和函数定义;

      res = let square x = x * x in (square 5, square 3, square 2)
            -- (25,9,4)
      
    • let表达式可用于列表推导式中的输出部分,此时let表达式位于输入后、谓词前,且in关键字可省略;

      calcBmis :: (RealFloat a) => [(a, a)] -> [a]
      calcBmis xs =
          [ bmi
          | (w, h) <- xs
          , let bmi = w / h ^ 2
          , bmi >= 25.0
          ]
      
    • let表达式用于谓词中时,不能省略in关键字;

      res = [ x | x <- [1..10], let cond = even x in cond ]
      
  • 区别:where语句为语法结构,是函数语法的一部分,只能单独使用,而let表达式为表达式,可用于任何表达式能用于的地方;

    res = 4 * (let a = 9 in a + 1) + 2 -- 42
    

if表达式#

if <condition> then <expression1> else <expression2>
  • if表达式:根据布尔值返回相应结果,若为True则返回expression1,否则返回expression2
  • if表达式与if语句不同,if语句中else可省略,而if表达式不可省略,因为必须有一个最终值;
  • Haskell 中if表达式不常用,通常使用守卫语法

多路if表达式#

{-# LANGUAGE MultiWayIf #-}
if | <condition> -> <result>
   ...
  • 多路if表达式:if表达式的扩展语法,允许if表达式进行多个条件的判断;
  • 语法格式:
    • if引领所有条件判断;
    • |后定义条件;
    • ->后定义条件为真时的解析结果;
  • 使用多路if表达式需要手动开启语法支持,添加{-# LANGUAGE MultiWayIf #-}于文件开头第一行即可;
{-# LANGUAGE MultiWayIf #-}
describeList :: [a] -> String
describeList xs = "The list is " ++ if
    | null xs        -> "empty."
    | length xs == 1 -> "a singleton list."
    | otherwise      -> "a longer list."

case表达式#

case <expression> of <pattern> -> <result>
                     ...
  • case表达式:对表达式进行模式匹配,并解析为相应结果;
  • 函数参数的模式匹配即为case表达式的语法糖;
  • 语法格式:
    • case关键字引领模式匹配;
    • case关键字后跟要进行匹配的表达式;
    • of关键字定义模式匹配,后跟多个模式,表达式依次与模式进行匹配;
    • ->后定义匹配成功后的解析结果;
  • 与函数参数的模式匹配不同,case表达式可以用于任何表达式能用于的地方;
describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of
    []  -> "empty."
    [x] -> "a singleton list."
    xs  -> "a longer list."