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

时间:2016-06-14 09:00:20

标签: 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])

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

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 值呢?

2 个答案:

答案 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个案例,必须与此参数具有相同的类型。

因此,使用Successfr作为返回值会将其类型限制为与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具有相同的函数类型,但此处未应用。

相反,创建新对象会给它一个新类型,它可以使用成功类型现在是第二种情况下函数结果的事实