在F#中解密类型说明

时间:2014-03-24 23:25:26

标签: f#

我经常在我正在阅读的书中看到如下的符号:

  

int - > int - > int * int

显然它是某种东西的类型

是否有指南可以解释如何阅读?它对我来说只是一个整体和箭头。

4 个答案:

答案 0 :(得分:8)

正如Jared所说,int -> int -> int * int类型可以作为返回函数的函数读取(接受int并返回元组)。您可以添加括号并将其读作int -> (int -> int * int)

返回函数的函数听起来有点混乱,并不是很有用。但实际情况并非F#中的情况,因为大多数情况下,您可以将此读取为将两个int值作为参数并返回一对int值的函数。

例如,使用余数执行除法的函数具有以下类型:

let divRem a b = (a/b, a%b)

现在,您可以将其视为两个参数的函数,只需编写:

divRem 10 3 // returns (3, 1)

这可能是更常见的情况。但您也可以将其视为一个返回函数的函数,并仅使用一个参数调用它:

let f = divRem 10
f 2  // returns (5, 0)
f 3  // returns (3, 1)
f 4  // returns (2, 2)

关于这一点的好处是,您可以轻松地使用多个不同的值作为第二个参数调用返回的函数。因此,因为F#用空格分隔参数,所以两种情况之间的区别较小。实际上,您可以将divRem 10 3视为(divRem 10) 3

在实践中,使用集合时这非常好。假设您希望获得将10除以1到9之间的所有数字的结果。您可以只写:

[ 1 .. 9 ] |> List.map (divRem 10)

答案 1 :(得分:6)

F#中的函数定义大致具有以下语法

[parameter] -> [return type]

让我们用这个语法将定义分解成碎片

int -> int -> int * int

在这种情况下,参数类型为int,返回类型为int -> int * int。仍然是一种奇怪的类型,所以让我们分析它

int -> int * int

这是一个需要int并返回int * int的函数。 *表示法用于表示元组。在这种情况下,一个有2个成员的元组,两种类型都是int

总而言之,它是一个函数,它接受int参数并返回一个函数,该函数接受int参数并返回int值的2个成员元组

答案 2 :(得分:1)

在F#中,有两种方法可以赋予函数多于参数的功能。让我们看一下只添加两个数字的函数。

 let f1 (x,y) = x + y       // f1 : int * int -> int      

这第一种方式看起来像许多其他语言,但在F#中,我们认为f1一个参数的函数,它恰好是两对。因此,您阅读的类型int * int -> int"给定int * int,我将返回int"。

 let f2 x y = x + y         // f2 : int -> int -> int 

第二种方式是箭头很多的方式。 f2仍然是两件事的功能,但现在我们一次给它一件事:

 let x = f2 10 5           // x = 15 : int

 let g = f 10              // g : int -> int
 let y = g 5               // y = 15 : int   

这由箭头表示。从技术上讲,我们应该阅读类型" int - > int - > INT" as"给定一个int,我将返回(给定一个int的函数返回一个int)"。或者更直接地,#34;给定一个int,然后另一个int,我将返回一个int"。

正如Tomas指出的那样,如果您想要对列表中的每个数字添加10,这通常很方便:

List.map (f2 10) [3; 5; 7; 11]        // = [13; 15; 17; 21]

计算机科学的一个着名结果是类型int -> int -> int只是一种不同(但更灵活)的类型int * int -> int的写法。我们甚至可以编写函数来进行转换:

let curry   f  x y  = f (x,y)
let uncurry f (x,y) = f  x y

通过这些功能,我们curry f1 = f2uncurry f2 = f1

答案 3 :(得分:1)

您可能更喜欢传统的数学符号:

ℤ → (ℤ → ℤ×ℤ)

它表示一个函数,它接受一个整数并返回一个函数,该函数接受另一个整数并返回一对整数。

FWIW,我在所有书籍和辅导课程中详细描述了语法。