我正在玩写结果类型和各种功能,并遇到了我无法解释的类型不匹配错误.这是一个最小的例子:
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值(此处为fr或xr)不起作用,但构造新的Failure值呢?
这里要理解的关键一点是,受歧视工会的类型涉及其所有情况。即使您“仅”重用Failure函数参数的实例作为返回值,所有返回值(包括case Success)也必须具有与该参数相同的类型。
因此,使用fr和作为返回值会限制它们的类型与 的返回类型xr相同。apply
但还有一行接受参数Success f并返回值Success (f x)! 如果这两个具有相同的类型,则 的类型f x必须是 的类型f!这是一个返回其自身类型的函数的函数,无论您应用它多少次;这种无限类型是不允许的,并且会导致编译器错误。
通过为返回值构建新实例,您可以允许apply的返回类型与其参数的类型不同。然后,编译器可以赋予f其返回值不同的类型,避免无限函数类型。