请考虑以下事项:
type T () =
member x.y = 4
let a =
let fn () (k: T) = ()
fn ()
let b =
let fn () (k: System.IO.Directory) = ()
fn ()
{p> a
在b
正常时失败。错误消息是:
当'_a:>时,值'a'被推断为具有泛型类型val a:('_ a - > unit) T将参数设为'a'显式,或者,如果您不打算将其作为通用参数,则添加类型注释
为什么以及如何解决这个问题?
答案 0 :(得分:6)
错误消息本身告诉您确切需要做什么 - 添加类型注释:
let a : T -> unit =
let fn () (k: T) = ()
fn ()
首先看到错误的原因是编译器试图概括a
的定义(参见规范的this part),这会产生您看到的奇怪签名在错误消息中。
您不需要为b
执行此操作的原因是System.IO.Directory
已被封存,因此无需进行概括。
答案 1 :(得分:1)
您正面临一个值限制,因为a
看起来像一个常量,但它返回一个函数。
看看这个问题:
Understanding F# Value Restriction Errors
解决这个问题的一种简单方法是在a
的定义中添加一个变量。
let a x =
let fn () (k: T) = ()
fn () x
我不知道为什么有些类型可行, b
答案 2 :(得分: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与上面代码中的任何内容无关,编译器仍然乐意接受任何类型的限制。