F# 类型
让我们从头开始。
F# 使用冒号 (:) 表示法来指示事物的类型。假设您定义了一个 int 类型的值:
let myNumber = 5
F# Interactive 会理解 myNumber 是一个整数,并会通过以下方式告诉您:
myNumber : int
读作
myNumber 的类型为 int
F# 函数类型
到目前为止一切顺利。让我们介绍一下其他东西,函数类型。函数类型只是函数的类型。 F# 使用-> 表示函数类型。这个箭头象征着写在它左边的东西变成了写在它右边的东西。
让我们考虑一个简单的函数,它接受一个参数并将其转换为一个输出。这种函数的一个例子是:
isEven : int -> bool
这将介绍函数的名称(在: 的左侧)及其类型。这一行可以用英文读为:
isEven 是类型函数,可将int 转换为bool。
请注意,要正确解释所讲的内容,您应该在“is of type”部分之后稍作停顿,然后立即阅读句子的其余部分,不要停顿。
在 F# 中,函数是值
在 F# 中,函数(几乎)并不比 普通 类型更特殊。它们是您可以传递给函数、从函数返回的东西,就像 bool、int 或字符串一样。
如果你有:
myNumber : int
isEven : int -> bool
您应该将int 和int -> bool 视为同一类型的两个实体:类型。这里,myNumber 是 int 类型的值,isEven 是 int -> bool 类型的值(这就是我在谈到 短暂停时想要表示的以上)。
功能应用
包含-> 的类型的值恰好也称为函数,并且具有特殊的能力:您可以将函数应用 一个值。所以,例如,
isEven myNumber
表示您正在将名为isEven 的函数应用于值myNumber。正如您通过检查isEven 的类型所期望的那样,它将返回一个布尔值。如果你正确实现了isEven,它显然会返回false。
返回函数类型值的函数
让我们定义一个通用函数来确定一个整数是否是其他整数的倍数。我们可以想象我们函数的类型将是(括号在这里帮助你理解,它们可能存在也可能不存在,它们有特殊含义):
isMultipleOf : int -> (int -> bool)
你可以猜到,这读作:
isMultipleOf 属于 (PAUSE) 函数类型,可将 int 转换为 (PAUSE) 函数,可将 int 转换为 bool。
(这里的(PAUSE)表示大声朗读时的停顿)。
我们稍后会定义这个函数。在此之前,让我们看看如何使用它:
let isEven = isMultipleOf 2
F# Interactive 会回答:
isEven : int -> bool
读作
isEven 的类型为 int -> bool
这里,isEven 的类型为 int -> bool,因为我们刚刚将值 2 (int) 赋予了 isMultipleOf,正如我们已经看到的,它将 int 转换为 int -> bool .
我们可以将这个函数isMultipleOf 视为一种函数创建者。
isMultipleOf的定义
现在让我们定义这个神秘的函数创建函数。
let isMultipleOf n x =
(x % n) = 0
简单吧?
如果你在 F# Interactive 中输入这个,它会回答:
isMultipleOf : int -> int -> bool
括号在哪里?
请注意,没有括号。现在这对你来说不是特别重要。请记住,箭头是右结合。也就是说,如果你有
a -> b -> c
你应该把它理解为
a -> (b -> c)
右结合中的right意味着你应该解释为好像最右边的运算符周围有括号。所以:
a -> b -> c -> d
应该解释为
a -> (b -> (c -> d))
isMultipleOf 的用法
所以,如您所见,我们可以使用isMultipleOf 来创建新函数:
let isEven = isMultipleOf 2
let isOdd = not << isEven
let isMultipleOfThree = isMultipleOf 3
let endsWithZero = isMultipleOf 10
F# Interactive 会回应:
isEven : int -> bool
isOdd : int -> bool
isMultipleOfThree : int -> bool
endsWithZero : int -> bool
但是您可以以不同的方式使用它。如果不想(或不需要)创建新函数,可以按如下方式使用:
isMultipleOf 10 150
这将返回 true,因为 150 是 10 的倍数。这与创建函数 endsWithZero 然后将其应用于值 150 完全相同。
其实函数应用是左关联的,也就是说上面这行应该解释为:
(isMultipleOf 10) 150
也就是说,您将括号放在最左边的函数应用程序周围。
现在,如果您能理解这一切,那么您的示例(即规范的 CreateAdder)应该是微不足道的!
前段时间有人问this question 处理完全相同的概念,但使用的是 Javascript。在我的回答中,我给出了两个规范示例(CreateAdder、CreateMultiplier)inf Javascript,它们对返回函数更加明确。
我希望这会有所帮助。