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

rys*_*ama 2 f# options pattern-matching

任何人都知道这段代码的问题是什么?

let rec Foo(a,b) =
    match a () with
    | None -> Some(b)
    | Some(c) -> Some(Foo(c,b))
Run Code Online (Sandbox Code Playgroud)

这是编译器错误:

"类型不匹配.期待'a但给定'一个选项结果类型在统一''a'和''选项'时将是无限的"

Ale*_*nov 8

让我们尝试重现编译器如何在此处推断类型.

let rec Foo(a,b) =
    match a () with
    | None -> Some(b)
    | Some(c) -> Some(Foo(c,b))
Run Code Online (Sandbox Code Playgroud)

"好吧,所以我明白了a ().a必须是unit某种类型的函数,我还不知道哪一种.我会称之为'a."

a : unit -> 'a
Run Code Online (Sandbox Code Playgroud)

"结果a ()None/ Somepatterns 相匹配.所以'a必须是a 'b option并且c有类型'b." (再次,'b代表一个未知的,至今,类型).

a : unit -> 'b option
? : 'b
Run Code Online (Sandbox Code Playgroud)

"没有调用任何函数或方法b(除了Some,它不会缩小类型,以及Foo到目前为止我们不知道的类型).我将用它来表示它的类型'c."

a : unit -> 'b option
b : 'c
c : 'b
Run Code Online (Sandbox Code Playgroud)

" Foo返回Some(b)的分支之一,因此,返回类型必须是'c option."

Foo : (unit -> 'b option) * 'c -> 'c option
Run Code Online (Sandbox Code Playgroud)

"我完成了吗?不,我需要检查表达式中的所有类型是否有意义.让我们看看,在这种Some(c)情况下,Some(Foo(c,b))返回.所以Foo(c,b) : 'c.因为Foo返回一个option,我知道'c必须'd option为某些'd,并且b : 'd.等等,我已经有b : 'c,那就是b : 'd option,'d'd option必须是同类型的,但是这是不可能的!必须有定义一个错误.我要报的." 它确实如此.