`
tianshibaijia
  • 浏览: 1128622 次
文章分类
社区版块
存档分类
最新评论

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# 和通常的函数语言与正常的面向对象,在对具有多个参数的函数的理解有不同的概念。

分享到:
评论

相关推荐

    Python核心编程(第二版).pdf (压缩包分2部分,第二部分)

     11.1.2 返回值与函数类型   11.2 调用函数   11.2.1 函数操作符   11.2.2 关键字参数  11.2.3 默认参数   11.2.4 参数组   11.3 创建函数   11.3.1 def语句   11.3.2 声明与定义比较   ...

    Python核心编程(第二版).pdf (压缩包分2部分,第一部分)

     11.1.2 返回值与函数类型   11.2 调用函数   11.2.1 函数操作符   11.2.2 关键字参数  11.2.3 默认参数   11.2.4 参数组   11.3 创建函数   11.3.1 def语句   11.3.2 声明与定义比较   ...

    Python核心编程第二版(ok)

     11.1.2 返回值与函数类型   11.2 调用函数   11.2.1 函数操作符   11.2.2 关键字参数  11.2.3 默认参数   11.2.4 参数组   11.3 创建函数   11.3.1 def语句   11.3.2 声明与定义比较   ...

    Python核心编程第二版

     11.1.2 返回值与函数类型   11.2 调用函数   11.2.1 函数操作符   11.2.2 关键字参数  11.2.3 默认参数   11.2.4 参数组   11.3 创建函数   11.3.1 def语句   11.3.2 声明与定义比较   ...

    精通WindowsAPI 函数 接口 编程实例

    5.5.2 获得当前系统内存使用情况 146 5.5.3 判断内存指针的可用性 147 5.6 各种内存分配方式的关系与比较 148 5.6.1 标准C内存管理函数与Windows内存管理API的关系 149 5.6.2 功能性区别 149 5.6.3 效率...

    SCILAB中文教程

    与MATLAB 类似,SCILAB也是一种科学工程计算软件,其数据类型丰富,可以很方便地实现各种矩阵运算与图形显示,能应用于科学计算、数学建模、信号处理、决策优化、线性/非线性控制等各个方面。它还提供可以满足不同...

    Excel公式与函数大辞典.宋翔(带书签高清文字版).pdf

    1.3.2 函数的类型 14 1.3.3 函数的参数 15 1.3.4 在公式中输入函数 16 1.4 在公式中使用名称 18 1.4.1 名称的作用范围 19 1.4.2 命名区域 19 1.4.3 命名公式 20 1.4.4 命名常量 21 1.4.5 将名称应用到公式...

    精通Windows.API-函数、接口、编程实例.pdf

    5.5.2 获得当前系统内存使用情况 146 5.5.3 判断内存指针的可用性 147 5.6 各种内存分配方式的关系与比较 148 5.6.1 标准C内存管理函数与Windows内存管理API的关系 149 5.6.2 功能性区别 149 5.6.3 效率...

    c++教案 ==========

    5.5.2单实例对象类· 24 第六章 复合数据类型· 24 6.1 变量与赋值的进一步讨论· 24 6.2 指针类型· 24 6.5 指向对象的指针· 25 6.5.1对象指针· 25 6.5.2 对象的动态创建与撤消· 26 6.5.3 对象...

    OCA认证考试指南1Z0-051

    4.1.2 函数类型 4.2 在SELECT语句中使用字符.数字和日期函数 4.2.1 使用字符大小写转换函数 4.2.2 使用字符操作函数 4.2.3 使用数字函数 4.2.4 使用日期 4.2.5 使用日期函数 4.3 认证小结 4.4 本章 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    7.1.6 结构体类型数据作为函数参数 *7.1.7 动态分配和撤销内存的运算符new和delete 7.2 共用体 7.2.1 共用体的概念 7.2.2 对共用体变量的访问方式 7.2.3 共用体类型数据的特点 7.3 校举类型 7.4 用typedef声明类型 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    7.1.6 结构体类型数据作为函数参数 *7.1.7 动态分配和撤销内存的运算符new和delete 7.2 共用体 7.2.1 共用体的概念 7.2.2 对共用体变量的访问方式 7.2.3 共用体类型数据的特点 7.3 校举类型 7.4 用typedef声明类型 ...

    WAP 无线应用协议

    5.5.2 一个扩展的示例 107 5.6 术语定义 109 5.7 缩略语 110 5.8 参考标准 110 5.9 参考资料 111 第6章 WMLScript语言规范 112 6.1 范围 112 6.2 概述 112 6.2.1 为什么需要脚本 112 6.2.2 使用WMLScript的好处 113 ...

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     5.5.2 continue语句 171  5.5.3 goto语句 172  5.6 TRY语句块和异常处理 172  5.6.1 throw表达式 173  5.6.2 try语句块 174  5.6.3 标准异常 176  小结 178  术语表 178  第6章 函数 181  6.1 函数基础 ...

Global site tag (gtag.js) - Google Analytics