运算符#

总览#

  • Haskell 中,所有运算符本质上均为函数,在 GHCi 中使用:type命令检查运算符类型时,须用小括号()包围;

    (+) :: Num a => a -> a -> a
    
  • Haskell 中,所有运算符都默认为中缀运算符,即参数分布在左右两侧,小括号()可以将运算符转换为前缀函数

    res1 = 2 + 3   -- 5
    res2 = (+) 2 3 -- 5
    
  • Haskell 中,使用一对反引号可将接受两个参数的函数转换为中缀运算符,此时左运算子作为第一个位置参数传入;

    addFunc :: Integer -> Integer -> Integer -- 函数定义
    addFunc x y = x + y
    
    res1 = addFunc 1 2
    res2 = 1 `addFunc` 2
    res1 == res2 -- True
    

算术运算符#

运算符 说明
+
-
*
/ 除(浮点)
quot 除(向零取整)
div 除(向负取整)
mod 取模
rem 取余
^ 幂(整幂)
^^ 幂(浮点底整幂)
** 幂(浮点底浮点幂)
  • /:两侧只接受浮点数为参数,否则报错;

    i :: Integer
    i = 3
    x = i / i
    -- The type signature for ‘i’ lacks an accompanying binding
    
  • divmod:Haskell 中整除和取模没有对应运算符,但有对应函数;

    x = (-7) `mod` 3 -- 2
    y = 3 `div` 2    -- 1
    
  • ^右侧只接受整数,^^左侧接受浮点数,右侧接受整数,**两侧只接受浮点数;

  • Haskell 中,任何时候负数都必须用括号包围,否则会识别为减号;

    z = (-3) * (-7)  -- returns 21
    z = -3 * -7
    -- Precedence parsing error
    --     cannot mix ‘*’ [infixl 7] and prefix `-' [infixl 6]
    --         in the same infix expression
    
  • 所有运算符两侧(除幂运算)必须为同一数值数据类型,Haskell 不作隐式类型转换;

    j :: Float
    k :: Double
    j = 3.2
    k = 3.2
    l = j + k
    -- Couldn't match expected type ‘Float’ with actual type ‘Double’
    

逻辑运算符#

运算符 说明
&& 逻辑与
|| 逻辑或
not 逻辑非
  • 谓词

    • 可进行真值判断的表达式,且该表达式决定是否执行后续操作;

      res1 = if "Haskell" > "C++" -- 谓词
          then 3
          else 4
      
    • 在函数参数的类型声明中,若该函数第一个参数为一个返回布尔值的函数,则该函数也称为谓词;

res1 = True && False
res2 = not (False || True)

比较运算符#

运算符 说明
== 等于
/= 不等于
> 大于
< 小于
<= 大于或等于
>= 小于或等于
  • 与其他语言不同,Haskell 使用/=作为不等于;

  • 当比较运算符两侧为字符时,比较字符的 Unicode 码,若为字符串,则从左向右依次比较;

  • 当比较运算符两侧为列表时,从左至右依次对每个元素进行比较(若均相对,则元素更多者更大);

    res = [3,4,2] > [3,4] -- True
    

固定性声明#

  • 固定性:即运算符的优先级,在 Haskell 中分为 0~9 共 10 个等级,数字越大运算优先级越高;

  • 结合性:Haskell 中分为左结合、右结合和无结合三种;

    • 左结合:首先与左运算子运算;
    • 右结合:首先与右运算子运算;
    • 无结合:不结合;
  • infix*关键字:

    infix <fixity> <operator>
    infixl <fixity> <operator>
    infixr <fixity> <operator>
    
    • infix:指定无结合运算符的固定性;
    • infixl:指定左结合运算符的固定性;
    • infixr:指定右结合运算符的固定性;
    • infix*关键字同样可以定义中缀函数的固定性;
  • 运算符命名:除少数保留字外,Haskell 中的运算符可以用任意非标识符字符定义;

    • 合法字符:!#$%&*+./=<?>@\~ˆ-:
    • 保留字:..:::=\|<-->@~=>
infixl 6 -?+
(-?+) :: (Num a, Ord a) => a -> a -> a
x -?+ y | x > y = x - y
        | otherwise = x + y

exp1 = 3 -?+ 2       -- 1
exp2 = 3 -?+ 4       -- 7
exp3 = 3 -?+ 2 -?+ 5 -- 6

内置运算符#

优先级 左结合 无结合 右结合
9 !!   .
8     ^, ^^, **
7 *, /, div, mod, rem, quot    
6 +, -    
5     :, ++
4   ==, /=, <, <=, >, >=, elem, notElem  
3     &&
2     ||
1 >>, >>=    
0     $, $!, seq