在结果类型中键入不匹配错误

dum*_*ulo 6 f#

我正在玩写结果类型和各种功能,并遇到了我无法解释的类型不匹配错误.这是一个最小的例子:

type ('a, 'b) result =
    | Success of 'a
    | Failure of 'b list

let apply fr xr =
    match fr, xr with
    | Success f, Success x -> Success (f x)
    | Failure _, Success _ -> fr
    | Success _, Failure _ -> xr
    | Failure a, Failure b -> Failure (List.concat [a; b])
Run Code Online (Sandbox Code Playgroud)

编译此代码会产生以下错误:

init.fsx(8,31): error FS0001: Type mismatch. Expecting a
('a,'b) result
but given a
(('c -> 'a),'d) result
The resulting type would be infinite when unifying ''a' and ''b -> 'a'
Run Code Online (Sandbox Code Playgroud)

如果您根据以下更改apply函数,它将正确编译:

let apply fr xr =
    match fr, xr with
    | Success f, Success x -> Success (f x)
    | Failure a, Success _ -> Failure a
    | Success _, Failure b -> Failure b
    | Failure a, Failure b -> Failure (List.concat [a; b])
Run Code Online (Sandbox Code Playgroud)

为什么使用匹配的over值(此处为frxr)不起作用,但构造新的Failure值呢?

Van*_*oiy 4

这里要理解的关键一点是,受歧视工会的类型涉及其所有情况。即使您“仅”重用Failure函数参数的实例作为返回值,所有返回值(包括case Success)也必须具有与该参数相同的类型。

因此,使用fr和作为返回值会限制它们的类型与 的返回类型xr相同。apply

但还有一行接受参数Success f并返回值Success (f x)! 如果这两个具有相同的类型,则 的类型f x必须是 的类型f!这是一个返回其自身类型的函数的函数,无论您应用它多少次;这种无限类型是不允许的,并且会导致编译器错误。

通过为返回值构建新实例,您可以允许apply的返回类型与其参数的类型不同。然后,编译器可以赋予f其返回值不同的类型,避免无限函数类型。