【问题标题】:Introductory F# (Fibonacci and function expressions)F# 入门(斐波那契和函数表达式)
【发布时间】:2017-01-10 12:08:04
【问题描述】:

我已经开始了 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);;

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

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

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

【问题讨论】:

  • 第一个有很多错误 - 为什么你有float 而且你可能需要更多缩进
  • 恭喜你开始学习F# ;)
  • 1.你看不出写函数f 和fib的区别吗?所以:let f = function |(n,0.0) -> g(n) |(x,n) -> h(x,n) 2. F# 是一种强类型语言:let g = fun n -> n + 4.0
  • 欢迎来到 Stack Overflow。您似乎在问两个不同的问题,这不适合该网站。当 SO 起作用时,您将获得帖子的答案。当您在同一篇文章中提出多个问题时,选择一个答案作为正确(或最佳)答案变得更加困难。这也许可以解释为什么还没有人打扰回答。考虑编辑您的帖子,使其只有一个问题。如果您还有更多问题,可以随时以单独帖子的形式提出。

标签: function f# functional-programming expression fibonacci


【解决方案1】:

我将处理您的第一个代码块,并将斐波那契函数留待以后使用。首先我会重新发布您的代码,然后我会谈论它。

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 函数仍然有错误。接下来让我们解决这个错误。

我认为您在这里犯的错误是认为fun 和function 是可以互换的。他们不是。 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 = 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 的错误用法,所以我不会重复他对你为什么会在这个词上出现错误的解释float 在您的 f 函数中。他还解释了;;,所以我也不会重复。我只想说,当他提到“任何带有将代码发送到 F# 交互(通过 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 的 Atom 版本更新频率较低,因为现在所有 Ionide 开发人员都使用 VS Code),这使得 F# 编辑成为一种真正的乐趣。实际上,您会发现三个扩展:Ionide-fsharp、Ionide-FAKE 和 Ionide-Paket。下载并安装所有这三个工具:FAKE 和 Paket 是您可能还不需要的两个 F# 编程工具,但是一旦您确实需要它们,您就已经安装了它们。

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

【讨论】:

  • 谢谢,这实际上解释了很多:)
【解决方案2】:

您的第一个 sn-p 主要有两个问题:

  • 在 F# 中,float 和 int 之间存在差异。您将整数值写入4 或0,并将浮点值写入4.0 或0.0。 F# 不会自动将整数转换为浮点数,所以需要保持一致。

  • f 函数中的语法有点奇怪 - 我不确定 float 应该是什么意思,fun 和 function 构造的行为不同。

所以,从您的原始代码开始:

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

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

但是,在您的 f 函数中,您想要返回 float,因此您需要修改 g 以返回 float。这意味着用4.0替换4:

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)

还要注意缩进很重要——| 之前需要空格。

【讨论】:

  • 非常感谢,我已经习惯了通过命名来指定变量类型的语言,而不是通过将 0 更改为 0.0 :P
猜你喜欢
  • 2014-05-03
  • 2017-07-08
  • 2011-02-16
  • 2021-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
相关资源
最近更新 更多