简体   繁体   English

类型和功能

[英]Types and functions

Consider the following: 考虑以下:

type T () =
  member x.y = 4

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

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

a fails while b is ok. a而未能b是确定的。 The error message is: 错误消息是:

The value 'a' has been inferred to have generic type val a : ('_a -> unit) when '_a :> T Either make the arguments to 'a' explicit or, if you do not intend for it to be generic, add a type annotation 值'a'被推断为具有泛型类型val a:('_a - > unit)当'_a:> T要么使参数'a'显式,要么如果你不打算使它是通用的,添加类型注释

Why and how to fix that? 为什么以及如何解决这个问题?

The error message itself tells you exactly what you need to do - add a type annotation: 错误消息本身告诉您确切需要做什么 - 添加类型注释:

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

The reason that you see the error in the first place is that the compiler tries to generalize the definition of a (see this part of the spec), which results in the odd signature that you see in the error message. 您看到的错误摆在首位的原因是编译器试图概括的定义a (见这部分的规范),这将导致你错误消息见奇签名。

The reason that you don't need to do this for b is that System.IO.Directory is sealed, so there is no need to generalize. 您不需要为b执行此操作的原因是System.IO.Directory已被密封,因此无需进行概括。

You are facing a value restriction, because a looks like a constant but it returns a function. 您正面临一个值限制,因为a看起来像一个常量,但它返回一个函数。 Have a look at this question: 看看这个问题:

Understanding F# Value Restriction Errors 了解F#值限制错误

One easy way to solve it is adding a variable to the definition of a . 一个简单的方法来解决它是加入一个变量来定义a

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

I don't know why with some types it works, which is the case of b 我不知道为什么它的某些类型有效,这就是b的情况

If T where a record instead of a class, it would work. 如果T所在的记录而不是类,那就行了。 But for some reason, you have to spell it out for the compiler if T is a class, 但出于某种原因,如果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.

edit: So I played a bit more with this, and weirdly, the compiler seems to be content with just any type restriction: 编辑:所以我用这个玩了一下,奇怪的是,编译器似乎满足于任何类型的限制:

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'

The type S has nothing to do with anything in the code above, still the compiler is happy to just have a restriction of any kind. 类型S与上面的代码中的任何内容无关,编译器仍然乐于接受任何类型的限制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM