5.5.2 函数类型

5.5.2 函数类型

 

    我们已经看到,在 F# 中,函数值的类型写成箭头符号,这是在很多方面类似于建造的元组的方式。早些时候,我们看到,可以从其他简单的类型,使用带类星号 (int * string)的类型构造函数,构造元组类型。函数类型以类似方式构造,只是使用函数类型构造函数 (int -> string)。在数学意义上,函数就是关系,为每个可能的输入指定返回值,而不是指定大量的这种关系的所有组合,只指定计算结果的代码,使用 lambda 函数。

    在 C# 中,也可以看到这种相似性。如果我们使用我们的元组的泛型类型和 Func 委托,可以重写上一段中的示例, Tuple<int, string> and Func<int, string>。而不是使用内置的类型,像我们可以在 F# 中做Func (或 Action) 委托之间有非常的重要区别:普通的 F# 函数类型与 写成 lambda 函数的等价的函数的类型相同 。在 C# 中,lambda 函数被转换为委托,委托与方法不是同一件事。这种区别是微妙的,但很重要:当考虑 F# 中有多个参数的函数时,我们将看得更清楚。之前,我们研究一下如何使用函数值作为参数值或返回值。

 

作为参数值和返回值的函数

 

    第 3 章中,我们已使用过函数作为参数值,在 C# 和 F# 中,对你来说,基本概念不应该是的新。然而,我们还没有以这种方式使用 lambda 函数。Lambda 函数是写一个函数的最简单方法,这个函数用于作为另一个函数的参数值。清单 5.17 提供了一个简单的例子。在救命开始的函数,取一个数和一个函数作为参数值,并两次调用这个函数,使用第一次调用的结果作为第二次调用的参数值。

 

Listing 5.17 Using a function as an argument in C# and F#

 

// C# version
int Twice(int input, Func f) {
  return f(f(input));
}
var result = Twice(2, n => n * n);

// F# version
> let twice (input:int) f = f(f(input));;
val twice : int -> (int -> int) –> int

> twice 2 (fun n -> n * n);;
val it : int = 16

 

    在此示例中,我们可以在一个地方看到所有重要的功能。它显示如何声明一个 C# 方法和 F# 函数,取函数作为参数值,以及如何使用 lambda 函数调用它们。在 F# 中,我们使用到类型注释,告诉 F# 编译器,我们只想使用整数。在下一章我们可以看到,没有这个注释,它可能自动使这个函数更为通用。这通常是可取的,但我们希望保持此示例尽可能简单。

    在 C# 版本中,Twice 是一个方法,有一个委托作为参数,而在 F# 版本中,它是一个函数。当我们看 F# 签名时,可以看到它的构造,只用了一个函数类型的构造函数 (箭头)。第二个参数是一个函数,取一个整数并返回一个整数,整体的类型是一个函数,有两个参数。

    因为函数是一个普通的值,也可以写一个函数(或在 C# 中的方法),返回函数作为结果。清单 5.18 显示了一个函数,取一个数字作为参数值,并返回一个函数,它把这个数字加到任何给定的参数值。

 

Listing 5.18 Using a function as a return value in C# and F#

 

C#F#

Func Adder(int n) {
  return (a) => a + n;
}

Func add10 =
  Adder(10);

var r = add10(15);
// Result: r == 25

> let adder(n) =
  (fun a -> a + n);;
val adder : int -> int –> int

> let addTen = adder 10;;
val addTen : (int -> int)

> addTen 15;;
val it : int = 25

 

    Adder 取一个 int 作为参数值,并返回一个函数作为结果。在 C# 中,显式指定了返回类型,是 Func 委托,而在 F# 中,返回类型是由类型推断推导出的,是一个函数,其类型为 int -> int。

    后面我们会看到,打印的类型签名表示,函数取一个整数并返回一个函数。如果我们给打印的签名加上括号,可以看得更清楚。那么,它将写成  int-> (int-> int)。

    调用这个返回函数的函数(或 C# 的方法),在 C# 中,其结果是一个委托,在 F# 中,是一个普通的函数。就像打印的类型签名所示的一样,它取整数作为参数值,并返回一个整数。

    调用返回的函数(或在 C# 中的 Func 委托),在 F# 中,我们使用它作为一个普通的函数,在 C# 中,我们把它称为委托。

    清单 5.18 使用一个简单的例子, 显示了如何使用一个函数作为返回值,但在后面几章中,我们将会看到,从另外的函数返回一个函数是有用的。关于这个代码,有一件事值得进一步解释。如果我们看看 F# Adder 函数的类型签名,可以看到其类型是 int-> int-> int。这看起来像一个函数,有两个参数,但像 int-> (int-> int),可能更容易理解。它们的意思是相同的,因为,F# 和通常的函数语言与正常的面向对象,在对具有多个参数的函数的理解有不同的概念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值