刚开始学习F#和我试图生成和评估泰勒系列的第10项è.我最初编写此代码来计算它:
let fact n = function
| 0 -> 1
| _ -> [1 .. n] |> List.reduce (*)
let taylor e =
let term n = (e ** n) / (fact n)
[1 .. 10]
|> List.map (term)
|> List.reduce (+)
Run Code Online (Sandbox Code Playgroud)
这导致错误,因为**
操作员不工作int
.显然,我需要将所有内容都投射到float
一起才能使一切正常工作.所以:
let fact (n: float) = function
| 0.0 -> 1.0
| _ -> [1.0 .. n] |> List.reduce (*)
let taylor (e: float) =
let term (n: float) = (e ** n) / (fact n)
[1.0 .. 10.0]
|> List.map (term)
|> List.reduce (+)
Run Code Online (Sandbox Code Playgroud)
这会产生编译器错误:
EvaluatingEtotheX.fs(9,39): error FS0001: The type 'float -> float' does not match the type
'float'
EvaluatingEtotheX.fs(9,36): error FS0043: The type 'float -> float' does not match the type
'float'
Run Code Online (Sandbox Code Playgroud)
(第9行是在哪里let term n = (e ** n) / (fact n)
).
为什么这不起作用?无论如何,这个错误究竟意味着什么?为什么编译器关心我传递的是一个产生float
而不是实际float
值的函数?请注意,我刚刚开始学习F#,所以我不熟悉为什么在这种情况下这不起作用.
您正在混合使用两种语法来定义fact
函数.
使用function
关键字时,它会隐式添加一个参数,然后在定义的分支中使用该参数.如果您检查fact
定义的签名,您将看到float -> float -> float
而不是float -> float
.定义中的第一个浮点数对应于n
,第二个浮点数由您使用function
关键字添加.
您可以使用function关键字
let fact = function
| 0.0 -> 1.0
| n -> [1.0 .. n] |> List.reduce (*)
Run Code Online (Sandbox Code Playgroud)
或显式匹配表达式(编译器将能够推断出类型为n
as float
,无需手动指定)
let fact n =
match n with
| 0.0 -> 1.0
| _ -> [1.0 .. n] |> List.reduce (*)
Run Code Online (Sandbox Code Playgroud)
旁注,即使在这种情况下不是实际问题,将浮点数与精确值进行比较通常不是一个好主意,因为它们的二进制表示.在你的情况下,继续fact
对整数进行操作然后转换结果可能是有意义的:
let term n = (e ** n) / (float (fact (int n))) // assumes fact : int -> int
Run Code Online (Sandbox Code Playgroud)