F# 入门(斐波那契和函数表达式)

Introductory F# (Fibonacci and function expressions)

我已经开始学习 F# 入门课程,但我在完成两项作业时遇到了一些问题。第一个让我创建两个函数,其中第一个函数接受一个输入并将其与四个相加,第二个函数计算 sqrt(x^2+y^2)。然后我应该为它们都编写函数表达式,但由于某种原因它给了我错误 "Unexpected symbol'|' in implementation file".

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);;

第二个作业要求我创建一个函数,用于查找斐波那契数列。我写了下面的代码,但它似乎忘记了开头的 0,因为输出总是 n+1 而不是 n。

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

请记住,这是第一周,所以我应该能够使用这些方法创建它们。

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

  • 在F#中,floatint是有区别的。您将整数值写为 40,将浮点值写为 4.00.0。 F#不会自动将整数转换为浮点数,所以需要保持一致。

  • 您在 f 函数中的语法有点奇怪 - 我不确定 float 应该是什么意思以及 funfunction 构造行为不同。

因此,从您的原始代码开始:

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

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

但是,在您的 f 函数中,您想要 return float 因此您也需要将 g 修改为 return 浮动。这意味着将 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只是一个 shorthand 用于编写函数然后在输入上进行模式匹配):

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)

另请注意缩进很重要 - | 之前需要空格。

我将处理您的第一段代码,斐波那契函数留待以后处理。先转一下你的代码,再说吧

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关键字是shorthand一个参数加一个匹配表达式。换句话说,这个:

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 = function (...) 替换那些 let f param = match param with (...) 表达式。但在 match param with (...) 真正深入理解之前,您应该继续明确地输入它。

所以您的 f 函数应该如下所示:

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

我看到当我输入这个时,Tomas Petricek 发布了一个回复,它解决了 float 的不正确用法,所以我不会重复他对你为什么会得到一个f 函数中的 float 字词错误。他还解释了 ;;,所以我也不会重复。我只想说,当他提到 "any decent editor with command for sending code to F# interactive (via Alt+Enter)" 时,有很多编辑器选择——但作为初学者,您可能只想有人向您推荐一个,所以我会推荐一个。不过,首先:如果您使用 Windows,您可能已经在使用 Visual Studio,在这种情况下,您应该坚持使用 Visual Studio,因为您知道它。它是 F# 的一个很好的编辑器。但是,如果您还没有使用 Visual Studio,我不建议您下载它只是为了玩弄 F#。这是一个程序的野兽,专为专业软件开发人员设计,可以完成他们在工作中需要做的各种事情,因此如果您刚刚开始使用它,可能会感到有点不知所措。所以我实际上会推荐一些更轻量级的东西:编辑器调用 Visual Studio 代码。它是跨平台的,将 运行 在 Linux、OS X 或 Windows 上完美运行。下载并安装 VS Code 后,您将需要安装 Ionide 扩展。 Ionide 是 VS Code 的插件(也适用于 Atom,尽管 Ionide 的 Atom 版本更新频率较低,因为现在所有 Ionide 开发人员都使用 VS Code),这使得 F# 编辑成为一种真正的乐趣。实际上,您会发现三个扩展:Ionide-fsharp、Ionide-FAKE 和 Ionide-Paket。下载并安装这三个工具:FAKE 和 Paket 是两个您可能不需要的 F# 编程工具,但是一旦您需要它们,您就已经安装了它们。

好的,我想这足以让你开始了。