我想知道这在F#中意味着什么
“取整数的函数,
返回一个取整数并返回整数的函数。”
但我不太了解这一点
有人能解释清楚这个吗?
[更新]:
> let f1 x y = x+y ;;
val f1 : int -> int -> int
这是什么意思?
答案 0 :(得分:57)
答案 1 :(得分:9)
这个典型的例子可能是“加法器创建者” - 一个函数,给定一个数字(例如3)返回另一个函数,该函数取一个整数并将第一个数字添加到它。
因此,例如,在伪代码中
x = CreateAdder(3)
x(5) // returns 8
x(10) // returns 13
CreateAdder(20)(30) // returns 50
我在F#中不够舒服,试图在没有检查的情况下编写它,但C#会是这样的:
public static Func<int, int> CreateAdder(int amountToAdd)
{
return x => x + amountToAdd;
}
这有帮助吗?
编辑:正如Bruno所说,你在问题中给出的例子就是我给出C#代码的例子,所以上面的伪代码将成为:let x = f1 3
x 5 // Result: 8
x 10 // Result: 13
f1 20 30 // Result: 50
答案 2 :(得分:7)
这是一个函数,它接受一个整数并返回一个取整数并返回整数的函数。
这在功能上等效于一个带两个整数并返回整数的函数。这种处理带有多个参数的函数的方法在函数式语言中很常见,并且可以轻松地部分地应用函数值。
例如,假设有一个add函数,它接受两个整数并将它们加在一起:
let add x y = x + y
您有一个列表,并且您希望为每个项目添加10。您将add
函数部分应用于值10
。它会将其中一个参数绑定到10并使另一个参数保持未绑定状态。
let list = [1;2;3;4]
let listPlusTen = List.map (add 10)
这个技巧使编写功能非常简单,并使它们非常可重用。如您所见,您不需要编写另一个向列表项添加10的函数,以将其传递给map
。您刚刚重用add
函数。
答案 3 :(得分:6)
您通常将此解释为一个采用两个整数并返回整数的函数。 您应该阅读currying。
答案 4 :(得分:2)
一个取整数的函数,它返回一个取整数并返回整数
的函数
最后一部分:
一个取整数并返回整数
的函数
应该相当简单,C#示例:
public int Test(int takesAnInteger) { return 0; }
所以我们留下了
一个取整数的函数,返回(类似上面的函数)
再次C#:
public int Test(int takesAnInteger) { return 0; }
public int Test2(int takesAnInteger) { return 1; }
public Func<int,int> Test(int takesAnInteger) {
if(takesAnInteger == 0) {
return Test;
} else {
return Test2;
}
}
答案 5 :(得分:1)
答案 6 :(得分:1)
在F#(以及许多其他函数式语言)中,有一个称为curried函数的概念。这就是你所看到的。基本上,每个函数都接受一个参数并返回一个值。
起初看起来有点令人困惑,因为你可以写let add x y = x + y
并且它似乎添加了两个参数。但实际上,原始的add
函数只接受参数x
。应用它时,它返回一个函数,该函数接受一个参数(y
)并且已填充x
值。然后,当您应用该函数时,它将返回所需的整数。
这在类型签名中显示。将类型签名中的箭头视为“将物品放在我的左侧并将物品返回到我的右侧”。在类型int -> int -> int
中,这意味着它接受类型为int
的参数 - 一个整数 - 并返回类型为int -> int
的函数 - 一个取整数并返回整数的函数。您会注意到这与上面的curry函数的工作原理完全匹配。
答案 7 :(得分:0)
示例:
let f b a = pown a b //f a b = a^b
是一个函数,它接受一个int(指数)并返回一个函数,该函数将其参数引发给该指数,如
let sqr = f 2
或
let tothepowerofthree = f 3
所以
sqr 5 = 25
tothepowerofthree 3 = 27
答案 8 :(得分:0)
这个概念被称为Higher Order Function,在函数式编程中很常见。
函数本身只是另一种类型的数据。因此,您可以编写返回其他函数的函数。当然,您仍然可以使用一个函数将int作为参数并返回其他内容。结合这两个并考虑以下示例(在python中):
def mult_by(a):
def _mult_by(x):
return x*a
return mult_by
mult_by_3 = mult_by(3)
print mylt_by_3(3)
9
(抱歉使用python,但我不知道f#)
答案 9 :(得分:0)
这里已有很多答案,但我想再提一下。有时以许多不同的方式解释同样的事情可以帮助你“理解”它。
我喜欢将功能视为“你给我一些东西,我会给你别的东西”
所以Func<int, string>
说“你给我一个int,我会给你一个字符串”。
我还发现用“以后”更容易思考:“当你给我一个int时,我会给你一个字符串”。当你看到诸如myfunc = x => y => x + y
之类的内容时,这一点尤其重要(“当你给了咖喱一个x,当你给它时,你会得到一些 的东西将会返回x + y“)。
(顺便说一句,我假设你在这里熟悉C#)
因此,我们可以将您的 int -> int -> int
示例表示为Func<int, Func<int, int>>
。
我看待 int -> int -> int
的另一种方式是通过提供适当类型的参数从左侧剥离每个元素。当你不再有->
时,你就没有了'laters'而且你得到了一个价值。
(只是为了好玩),你可以转换一个函数,它将所有它的参数一次性转换成一个逐渐“逐渐”的函数(逐步应用它们的官方术语是'部分应用'),这称为'currying' “:
static void Main()
{
//define a simple add function
Func<int, int, int> add = (a, b) => a + b;
//curry so we can apply one parameter at a time
var curried = Curry(add);
//'build' an incrementer out of our add function
var inc = curried(1); // (var inc = Curry(add)(1) works here too)
Console.WriteLine(inc(5)); // returns 6
Console.ReadKey();
}
static Func<T, Func<T, T>> Curry<T>(Func<T, T, T> f)
{
return a => b => f(a, b);
}
答案 10 :(得分:0)
这是我的2 c。默认情况下,F#功能可以启用部分应用或currying。这意味着你定义它:
let adder a b = a + b;;
您正在定义一个取和整数的函数,并返回一个取整数并返回整数或int -> int -> int
的函数。 Currying然后允许您部分应用函数来创建另一个函数:
let twoadder = adder 2;;
//val it: int -> int
上面的代码将a预先设定为2,因此每当你调用twoadder 3
时,它只会在参数中添加两个。
函数参数用空格分隔的语法等同于这个lambda语法:
let adder = fun a -> fun b -> a + b;;
这是一种更易读的方法,可以确定这两个函数实际上已被链接。