我正在玩写一个结果类型和各种各样的函数,并遇到了一个我无法解释的类型不匹配错误。这是一个最低限度的例子:
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])
编译此代码会产生以下错误:
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'
如果您根据以下内容更改 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])
为什么使用匹配的over值(此处 fr 或 xr )不起作用,但构建新的 Failure 值呢?
答案 0 :(得分:4)
这里要理解的关键是,受歧视的联盟的类型涉及其所有案例。即使您“仅”从函数参数中重用var inputString = "lorem ipsum !bang #hash #hash2 ^caret word @at sym";
var specialChars = "!#^@";
var firstSpecialCharIndex = inputString.search(/[!#^@]/);
var plainText = inputString.substring(0, firstSpecialCharIndex);
var result = {};
result["text"] = plainText;
for (i = firstSpecialCharIndex + 1; i < inputString.length;) {
var modifiedString = inputString.substring(i);
var currentChar = inputString.charAt(i - 1);
if (result[currentChar] == null)
result[currentChar] = [];
var text = "";
var specialCharIndex = modifiedString.search(/[!#^@]/);
if (specialCharIndex != -1) {
text = modifiedString.substring(0, specialCharIndex);
text = text.trim();
result[currentChar].push(text);
i += specialCharIndex + 1;
} else {
text = modifiedString.substring(0);
text = text.trim();
result[currentChar].push(text);
i = inputString.length;
}
}
console.log(result);
的实例作为返回值,所有返回值,包括 Failure
个案例,必须与此参数具有相同的类型。
因此,使用Success
和fr
作为返回值会将其类型限制为与xr
的返回类型相同。
但是还有一行将apply
的参数设为返回值Success f
!如果这两个类型相同,则Success (f x)
的类型必须是f x
的类型!这是一个函数,它返回一个自己类型的函数,无论你应用它多少次;不允许这样的无限类型并导致编译器错误。
通过为返回值构建新实例,允许f
的返回类型与其参数的类型不同。然后,编译器可以给apply
及其返回值不同的类型,避免使用无限函数类型。
答案 1 :(得分:2)
这是错误。
在这一行:
Success f, Success x -> Success (f x)
您将'a
定义为函数类型,因此返回'a
也是一个函数。
但是当你做的时候
| Failure _, Success _ -> fr
此fr
具有相同的函数类型,但此处未应用。
相反,创建新对象会给它一个新类型,它可以使用成功类型现在是第二种情况下函数结果的事实