类型和功能

时间:2012-02-03 12:46:41

标签: function types f#

请考虑以下事项:

type T () =
  member x.y = 4

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

let b =
  let fn () (k: System.IO.Directory) = ()
  fn ()
{p> ab正常时失败。错误消息是:

  

当'_a:>时,值'a'被推断为具有泛型类型val a:('_ a - > unit) T将参数设为'a'显式,或者,如果您不打算将其作为通用参数,则添加类型注释

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

3 个答案:

答案 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与上面代码中的任何内容无关,编译器仍然乐意接受任何类型的限制。