2012-02-03 63 views
4

考虑以下几点:类型和功能

type T() = 
    member x.y = 4 

let a = 
    let fn() (k: T) =() 
    fn() 

let b = 
    let fn() (k: System.IO.Directory) =() 
    fn() 

ab是确定的失败。错误消息是:

当'_a:> T或者将参数设置为'a'时,值'a'已被推断为泛型类型val a:('_a - > unit)如果你不打算这是通用的,添加一个类型注释

为什么以及如何解决这个问题?

回答

6

错误消息本身会告诉你到底你需要做的是什么 - 添加类型注释:

let a : T -> unit = 
    let fn() (k: T) =() 
    fn() 

,你看到的错误摆在首位的原因是编译器试图概括的定义a(请参阅规范的this part),这会导致您在错误消息中看到的奇怪签名。

你不需要这样做的原因是bSystem.IO.Directory是密封的,所以不需要一概而论。

1

您正面临价值限制,因为a看起来像一个常量,但它返回一个函数。 看一看这个问题:

Understanding F# Value Restriction Errors

一个简单的方法来解决它是加入一个变量的a定义。

let a x = 
    let fn() (k: T) =() 
    fn() x 

我不知道为什么有些类型它的工作原理,这是b

+0

但是,向定义中添加'x'会将'a'从函数值更改为函数,这意味着它不会在启动过程中进行评估。有关完整的解释,请参见[F#值,函数和一点点](http://blog.wezeku.com/2010/08/01/values-functions-and-a-bit-of-both)。 – 2012-02-03 14:07:19

0

如果T,其中一条记录,而不是一类,它会工作的情况。但由于某些原因,你必须拼出来的,如果T是一个类的编译器,

type T() = 
    member x.y = 4 

let a<'U when 'U :> T> = 
    let fn() (k: 'U) =() 
    fn() 

let test0 = a<T> (T()) // You can be explicit about T, 
let test1 = a (T())  // but you don't have to be. 

编辑:所以我打得多一点这个,和古怪,编译器似乎满足于仅仅任何类型的限制:

type T() = 
    member x.y = 4 

type S() = 
    member x.z = 4.5 

let a<'U when 'U :> S> = 
    let fn() (k: T) =() 
    fn() 

let test = a (T())  // Is OK 
let test = a<T> (T()) // Error: The type 'T' is not compatible with the type 'S' 

S型无关,与上面的代码中任何东西,还编译器是幸福的,只是有什么样的限制。