跳转到内容

Haskell/类型杂谈

来自维基教科书,自由的教科书

到目前为止,我们只接触过整数和列表,虽然也略微提到了字符串和字符。本节将涵盖主要的类型。

理解 Haskell 的内置类型的一个重要方面是,它们并不特殊。从编译器的角度来看,它们很特殊,因为处理器有专门的操作来进行整数加法等操作。但从程序员的角度来看,它们只是普通的类型,拥有普通的函数,遵循与其他类型相同的规则。因此,本节内容很少解释如何使用这些类型或规则是什么,因为大多数情况下您已经了解了它们:如果它适用于整数,那么它也适用于字符串、布尔值和浮点数。

Haskell 有两种整数类型:Int 和 Integer。

"Integer" 是任意精度的类型:它可以保存任意大的数字,直到机器内存的限制。这就是为什么 "factorial 1000" 会给出正确答案的原因。这意味着您永远不会遇到算术溢出。另一方面,这也意味着您的算术运算相对缓慢。Lisp 用户可能认出这里的 "bignum" 类型。

"Int" 是更常见的 32 或 64 位整数。实现方式可能有所不同,但保证至少为 30 位。

Haskell 也有两种浮点类型:Float 和 Double。它们的行为类似于 C 中的对应类型。

算术运算符

[编辑 | 编辑源代码]

所有常见的运算符都存在,还有一些额外的运算符。

旁注:Haskell 的数字类型在类型类的复杂层次结构中相互关联,这些类型类将在后面介绍。本页的目的是让您能够进行普通的算术运算,而不会被类型系统绊倒。

有三个 "幂运算" 运算符,它们的工作方式不同,接受的类型也不同。

**
接受两个浮点数,使用对数来计算幂。
^^
接受一个分数(例如浮点数或比例,后面会讲到)并将其提升到正或负整数幂。
^
接受任何数字类型并将其提升到正整数幂。

从整数类型(Int 或 Integer)转换为其他任何类型是通过 "fromIntegral" 完成的。目标类型是自动推断的。例如

n :: Integer
n = 6
x :: Float
x = fromIntegral n

m :: Int
m = 7
y :: Double
y = fromIntegral m

将定义 x 为 6.0,y 为 7.0。

整数除法有点复杂。如果您对整数使用普通的 "/" 运算符,那么您会收到错误消息(虽然表达式 "4/3" 可以工作,因为 Haskell 会在必要时将文字整数提升为浮点数)。相反,整数除法是使用一组命名的运算符完成的。

Haskell 在运算符方面有一个巧妙的技巧:您可以将任何接受两个参数的函数用反引号括起来,使其像运算符一样使用。因此,以下两行表示完全相同的意思

 d = 7 `div` 3
 d = div 7 3

考虑到这一点,以下是整数除法运算符

quot
返回两个数字的商。这是除法运算的结果,然后被截断为零。
rem
返回商的余数。
div
类似于 "quot",但向下舍入到负无穷。
mod
返回两个数字的模。这类似于余数,但在 "div" 返回负数时有不同的规则。

只要 y 不是负数,以下两个方程始终成立

(x `quot` y)*y + (x `rem` y) == x
(x `div`  y)*y + (x `mod` y) == x

就像您可以将接受两个参数的函数转换为运算符一样,您也可以将运算符转换为接受两个参数的函数:只需将其放在括号中。因此,以下两行表示相同的意思

(+) 3 4
3 + 4

这也可以对任何 "不完整的" 运算符应用进行

(3+) 4
(+4) 3 -- not 3 (+4)

布尔值

[编辑 | 编辑源代码]

Haskell 具有布尔类型Bool,有两个值TrueFalse。该类型上还定义了两个运算符Bool类型&&||.

数字、字符和字符串可以使用通常的比较运算符进行比较,以生成一个 Bool 值

==
相等。
/=
不相等。
<=
小于或等于。
>=
大于或等于。
<
小于。
>
大于。

(当您了解到 类型类 时,请注意,相等运算符 (==, /=) 是类型类的一部分Eq,比较运算符 (<=, >=, <, >) 是类型类的一部分Ord.)

Haskell 有一个 "if-then-else" 子句,但由于 Haskell 是一种函数式语言,它更类似于 C 中的 "? :" 运算符:它不是 "执行" "then" 子句或 "else" 子句,而是整个表达式计算出其中一个子句的值。例如,阶乘函数可以写成

factorial n =
   if n <= 0
      then 1
      else n * factorial (n-1)

一个if表达式的语法是

  if <condition> then <true-value> else <false-value>

如果条件为 True,那么 "if" 的结果就是真值,否则就是假值。

华夏公益教科书