F# 有人能解释一下我的编译器错误吗?

F# 有人能解释一下我的编译器错误吗?,f#,pattern-matching,options,F#,Pattern Matching,Options,有人知道这个代码有什么问题吗 let rec Foo(a,b) = match a () with | None -> Some(b) | Some(c) -> Some(Foo(c,b)) 以下是编译器错误: “类型不匹配。预期为'a,但给定了'a'选项。当统一'a'和'a选项'时,结果类型将是无限的。您正在使用a()作为选项,该选项是Foo中的第一个参数,但在最后一行c是一个类型,但您将其传递到递归调用中 这就是导致错误的原因 您可能希望将c作为一种选项

有人知道这个代码有什么问题吗

let rec Foo(a,b) =
    match a () with
    | None -> Some(b)
    | Some(c) -> Some(Foo(c,b))
以下是编译器错误:

“类型不匹配。预期为'a,但给定了'a'选项。当统一'a'和'a选项'

时,结果类型将是无限的。您正在使用
a()
作为选项,该选项是
Foo
中的第一个参数,但在最后一行
c
是一个类型,但您将其传递到递归调用中

这就是导致错误的原因


您可能希望将
c
作为一种选项类型。

逐步细分总是有帮助的。如前所述,Foo的类型为:

val Foo : (unit -> 'a option) * 'b -> 'b option
'b option
活动模式中的每个表达式都必须计算为相同的类型。表达式中的第一个模式匹配具有以下类型:

val Foo : (unit -> 'a option) * 'b -> 'b option
'b option
因此,其他模式也必须计算为
'b选项
'a选项
。按照您在这里使用的方式,它将返回一个选项

Foo : (unit -> 'b option) * 'c -> 'c option
这是一个特殊的函数,但是您可以通过在第二个模式匹配中返回任何选项值来纠正编译器错误。这是我能想到的唯一一个类似于上面的例子:

let Foo2(a,b) =
    match a () with
    | None -> Some(b)
    | c    -> c

HTH.

让我们尝试重现编译器在这里如何尝试推断类型

let rec Foo(a,b) =
    match a () with
    | None -> Some(b)
    | Some(c) -> Some(Foo(c,b))
“好的,我看到
a()
a
必须是从
unit
到某种类型的函数,我还不知道是哪一个。我将其称为
'a

“a()的结果与
/
某些
模式匹配。因此
'a
必须是
'b选项
c
的类型为
'b
”(同样,
'b
表示未知的类型)

“在
b
上没有调用任何函数或方法(除了
Some
,它没有缩小类型范围,以及
Foo
,到目前为止我们还不知道它的类型)。我将用
'c
来表示它的类型。”

Foo
返回其中一个分支中的
Some(b)
,因此返回类型必须是
'c option


“我完成了吗?没有,我需要检查表达式中的所有类型是否有意义。让我们看看,在
Some(c)
案例中,
Some(Foo(c,b))
被返回。因此
Foo(c,b):'c
。由于
Foo
返回一个
选项
,我知道
'c
必须是
'd选项
,对于某些
'd
,和
b:'d
。等等,我已经有了
b:'c
,也就是说,
b:'d选项
'd
必须是同一类型,但这是不可能的re一定是定义中的一个错误。我需要报告它。”确实如此。

只是为了好玩,你到底想做什么?也许有人可以建议一种更好的方法来编写你的函数。@Juliet-我不知道如何更好地编写函数,但在你提到它之前,我没有想到我会因为缺乏理解而停止编写函数。
Foo
没有这种类型,事实上,没有任何其他类型;这就是错误所在!我理解你的观点,但我从VisualStudio的F#解释器那里复制了这个签名。是的,代码不会如图所示编译或运行,但F#确实做了相当大的努力很好。换言之,编译器在“a”和“a”选项之间摇摆不定。。。选择权等。
Foo : (unit -> 'b option) * 'c -> 'c option