介绍F#(斐波那契和函数表达式)

时间:2016-09-02 11:30:04

标签: function f# functional-programming expression fibonacci

我已经开始介绍F#的课程,我在两个作业中遇到了一些麻烦。第一个让我创建两个函数,其中第一个函数接受输入并将其添加四个,第二个函数计算sqrt(x ^ 2 + y ^ 2)。然后我应该为它们写两个函数表达式,但由于某种原因它给了我错误"意外的符号' |'在实施文件"。

let g = fun n -> n + 4;;

let h = fun (x,y) -> System.Math.Sqrt((x*x)+(y*y));;

let f = fun (x,n) -> float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;

第二个作业要求我创建一个函数,它找到Fibonaccis数的序列。我已经编写了下面的代码,但它似乎忘记了开头的0,因为输出总是n + 1而不是n。

let rec fib = function
|0 -> 0
|1 -> 1
|n -> fib(n-1) + fib(n-2)
;;

请记住,这是第一周,因此我应该能够使用这些方法创建这些方法。

2 个答案:

答案 0 :(得分:5)

您的第一个代码段主要有两个问题:

  • 在F#中,floatint之间存在差异。您将整数值写为40,并将浮点值写为4.00.0。 F#不会自动将整数转换为浮点数,因此您需要保持一致。

  • f函数中的语法有点奇怪 - 我不确定float应该代表什么,fun和{{1构造行为不同。

所以,从原始代码开始:

function

这样可行,但我不会使用let g = fun n -> n + 4;; 将其写为显式函数 - 您也可以使用fun来定义函数,并且它更简单。此外,您只需要在F#Interactive中使用let,但如果您使用任何合适的编辑器来命令将代码发送到F#interactive(通过Alt + Enter),则不需要。

但是,在;;函数中,您希望返回f,因此您需要修改float以返回浮点数。这意味着将g替换为4

4.0

let g n = n + 4.0 功能很好,但您可以使用h再次编写它:

let

let h (x,y) = System.Math.Sqrt((x*x)+(y*y));; 函数中,您可以使用f使用模式匹配编写函数,也可以使用function使用更详细的语法(match只是写入函数的简写,然后在输入上进行模式匹配):

function

另请注意,缩进很重要 - 在let f = function | (n,0.0) -> g(n) | (x,n) -> h(x,n) let f (x, y) = match (x, y) with | (n,0.0) -> g(n) | (x,n) -> h(x,n) 之前需要空格。

答案 1 :(得分:3)

我将解决你的第一个代码块,并保留Fibonacci函数以供日后使用。首先我会重新发布你的代码,然后我会谈论它。

let g = fun n -> n + 4;;

let h = fun (x,y) -> System.Math.Sqrt((x*x)+(y*y));;

let f = fun (x,n) -> float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;

第一条评论:如果您要定义一个函数并立即将其分配给名称,就像在所有这些示例中一样,您不需要fun关键字。定义函数的常用方法是将它们写为let (name) (parameters) = (function body)。所以上面的代码将成为:

let g n = n + 4;;

let h (x,y) = System.Math.Sqrt((x*x)+(y*y));;

let f (x,n) = float
|(n,0) -> g(n)
|(x,n) -> h(x,n);;

我没有进行任何其他更改,因此您的f函数仍然存在错误。让我们接下来解决这个错误。

我认为你在这里犯的错误是认为funfunction是可以互换的。他们不是。 fun是标准函数定义,但function是其他内容。在F#中编写如下函数是非常常见的模式:

let someFunc parameter =
    match parameter with
    | "case 1" -> printfn "Do something"
    | "case 2" -> printfn "Do something else"
    | _ -> printfn "Default behavior"

function关键字是一个参数加上匹配表达式的简写。换句话说,这个:

let someFunc = function
    | "case 1" -> printfn "Do something"
    | "case 2" -> printfn "Do something else"
    | _ -> printfn "Default behavior"

与此完全相同:

let someFunc parameter =
    match parameter with
    | "case 1" -> printfn "Do something"
    | "case 2" -> printfn "Do something else"
    | _ -> printfn "Default behavior"

只有一个区别。在具有function关键字的版本中,您无法选择参数的名称。它由F#编译器自动创建,由于您无法事先知道参数的名称是什么,因此您无法在代码中引用它。 (好吧,有办法,但我不想让你学会在学会走路之前跑步,可以这么说)。还有一件事:当你还在学习F#时,我强烈建议你不要使用function关键字。一旦你知道自己在做什么,它就非常有用,但在你早期的学习阶段,你应该使用更明确的match (parameter) with表达式。这样你就会习惯看到它在做什么。一旦你做了几个月的F#,你就可以开始用较短的let f param = match param with (...)替换那些let f = function (...)表达式。但是在match param with (...)真正沉入并且你已经理解它之前,你应该继续明确地输入它。

所以你的f函数看起来应该是这样的:

let f (x,n) =
    match (x,n) with
    |(n,0) -> g(n)
    |(x,n) -> h(x,n);;

我看到,当我输入此内容时,Tomas Petricek发布了一个回复,它解决了float的错误用法,所以我不会复制他为什么会出现错误的解释float函数中的单词f。他还解释了;;,所以我也不会重复。我只想说,当他提到“任何体面的编辑器命令将代码发送到F#interactive(通过Alt + Enter)”时,有很多编辑器选择 - 但作为初学者,你可能只是想让某人推荐一个给你,所以我会推荐一个。首先,如果你在Windows上,你可能已经在使用Visual Studio,在这种情况下你应该坚持使用Visual Studio,因为你知道它。这是F#的好编辑。但是如果你还没有使用Visual Studio,我不建议下载它只是为了玩F#。它是一个程序的野兽,专为专业软件开发人员设计,可以完成他们在工作中需要做的各种事情,所以如果你刚刚开始,它会感觉有点压倒性。所以我实际上会推荐一些更轻量级的东西:编辑器叫做Visual Studio Code。它是跨平台的,在Linux,OS X或Windows上运行良好。下载并安装VS Code后,您将需要安装Ionide扩展。 Ionide是VS Code的插件(也是Atom的插件,虽然因为所有Ionide开发人员现在都使用VS Code,因此Ionode的Atom版本更新频率较低),这使得F#编辑成为一种真正的乐趣。实际上你会发现三种扩展:Ionide-fsharp,Ionide-FAKE和Ionide-Paket。下载并安装所有这三个:FAKE和Paket是F#编程的两个工具,你可能还不需要,但是一旦你需要它们,你就已经安装了它们。

好吧,我认为这足以让你开始。