“int - > int - > int”这在F#中意味着什么?

时间:2010-02-01 10:23:21

标签: f# functional-programming currying

我想知道这在F#中意味着什么 “取整数的函数,
返回一个取整数并返回整数的函数。”

但我不太了解这一点 有人能解释清楚这个吗?

[更新]:

> let f1 x y = x+y ;;

 val f1 : int -> int -> int

这是什么意思?

11 个答案:

答案 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;;

这是一种更易读的方法,可以确定这两个函数实际上已被链接。