2016-06-14 56 views
6

我在编写结果类型和各种函数时遇到了问题,并遇到了我无法解释的类型不匹配错误。下面是一个最小的例子:结果类型中的类型不匹配错误

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' 

,它编译正确:

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]) 

为什么使用匹配的超值(这里是frxr)无法正常工作,但构建新的失败值呢?

回答

4

关键一点需要了解函数的结果是,该类型一个受到歧视的工会关注其所有案件。即使您仅“重复使用来自函数参数Failure的实例作为返回值,全部返回值,包括Success的情况下,必须具有与此参数相同的类型。

因此,使用frxr作为返回值将其类型限制为与apply的返回类型相同。

但也有一条线将Success f的参数设置为返回值Success (f x)!如果这两个类型相同,f x的类型必须是f的类型!无论您应用了多少次,该函数都会返回它自己类型的函数;这种无限类型是不允许的,并导致编译器错误。

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

2

这是错误。

在这一行:

Success f, Success x -> Success (f x) 

定义'a是一个函数类型,因此你的回报'a也是一个函数。

但是当你做

| Failure _, Success _ -> fr 

fr具有相同的功能类型,但这里是未核销。

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

+0

谢谢约翰。目前还不清楚为什么第一场比赛可以替代 '| |成功f,成功x - >成功(f x)' 应该对第二场比赛有任何影响 '| |失败_,成功_ - > fr' 对我来说听起来像编译器中不必要的限制... – dumetrulo

+0

问题是'fr'与'Success(fx)'具有不同的类型,并且表达式需要返回变量相同的类型。 –