类型'浮动 - >浮'不匹配类型'浮动'

时间:2017-02-17 00:55:05

标签: types casting f#

刚开始学习F#,我正在尝试为 e 生成和评估泰勒系列的前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 (+)

由于**运算符不适用于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 (+)

产生编译器错误:

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'

(第9行是let term n = (e ** n) / (fact n)所在的位置。)

为什么这不起作用?无论如何,这个错误究竟意味着什么?为什么编译器关心我传递了一个产生float而不是实际float值的函数?请注意,我刚开始学习F#,所以我不熟悉为什么在这种情况下不能工作。

1 个答案:

答案 0 :(得分:8)

您正在混合使用两种语法来定义fact函数。

使用function关键字时,它会隐式添加一个参数,然后在定义的分支中使用。如果您检查fact定义的签名,则会看到float -> float -> float而不是float -> float。您定义中的第一个浮点数对应n,第二个浮点数是您使用function关键字添加的。

您可以使用函数关键字

let fact = function
    | 0.0 -> 1.0
    | n -> [1.0 .. n] |> List.reduce (*)

或显式匹配表达式(编译器将能够将n的类型推断为float,无需手动指定)

let fact n =
    match n with
    | 0.0 -> 1.0
    | _ -> [1.0 .. n] |> List.reduce (*)

旁注,即使在这种情况下它不是一个实际问题,将浮点数与精确值进行比较通常不是一个好主意,因为它们的二进制表示。在你的情况下,让fact对整数进行操作然后转换结果可能是有意义的:

let term n = (e ** n) / (float (fact (int n))) // assumes fact : int -> int