我经常在我正在阅读的书中看到如下的符号:
int - > int - > int * int
显然它是某种东西的类型。
是否有指南可以解释如何阅读?它对我来说只是一个整体和箭头。
答案 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
= f2
和uncurry f2
= f1
。
答案 3 :(得分:1)
您可能更喜欢传统的数学符号:
ℤ → (ℤ → ℤ×ℤ)
它表示一个函数,它接受一个整数并返回一个函数,该函数接受另一个整数并返回一对整数。
FWIW,我在所有书籍和辅导课程中详细描述了语法。