在什么条件下单位是类型? [英] Under what conditions is unit a type?

查看:85
本文介绍了在什么条件下单位是类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将此标记为重复之前:我知道这个问题与使用unit作为类型参数时有关编译错误的各种问题有关.一些例子:

Before this gets marked as a duplicate: I'm aware that this question is related to various questions about compilation errors when using unit as a type argument. Some examples:

  • Why is unit treated differently by the F# type system when used as a generic interface argument?
  • F# interface inheritance failure due to unit
  • Using unit as Type Parameter and overriding methods

这些都遇到了与此类似的问题:

These are all running into a problem similar to this one:

type Interface<'a> = 
    abstract member MyFunc : unit -> 'a

let implementingInstance =
  { new Interface<_> with
        member __.MyFunc () = () } // Compiler error!

据我了解,代码无法编译,因为使用void编译的单位返回函数是在内部返回的,这是CLI的一个附加功能,而不是类型.

From what I understand, the code does not compile because a unit-returning function gets compiled with void return internally, which is an extra feature of the CLI rather than a type.

但是!以下内容似乎可以满足编译器的要求:

However! The following seems to satisfy the compiler:

type RecordVersion<'a> =
  { MyFunc : unit -> 'a }

let recordInstance =
  { MyFunc = ignore }

如果我用lambda或let绑定的模块函数替换ignore,这也将起作用.

This also works if I replace ignore with a lambda or a let-bound module function.

对我来说,这只是完全相同的另一种表述. (尽管与F#设计指南不一致,F#设计指南建议使用接口而不是带有函数的记录类型.)

To me, this is just another formulation of the exact same thing. (Though at odds with the F# design guidelines, which suggest to prefer interfaces over function-carrying record types.)

我对设计API感兴趣,这些API的用户指定了所使用的行为和类型.因此,我想避免发生意外和令人困惑的编译器错误的情况.但是我不太确定该怎么做.看起来F#的功能性"函数 do 将单位视为一种类型.

I'm interested in designing APIs whose users specify the behavior and types used. Therefore, I would like to avoid cases where unexpected and confusing compiler errors occur. But I'm not quite sure what to make of this. It looks like F#'s "functional" functions do treat unit as a type.

此类单位虚假错误的确切条件是什么?是否可以通过打破设计准则并使用功能记录而不是接口来避免在API中使用它们? (我不太介意,但不确定是否能彻底解决问题.)

What are the exact conditions for such spurious errors with unit? Can I avoid them in my API by breaking the design guidelines and using records of functions instead of interfaces? (I wouldn't mind much, but I'm not sure if it solves the problem for good.)

推荐答案

我相信规则是,静态已知具有返回类型unit的方法将被编译为具有返回类型void的.NET方法.在.NET类型系统中(通过静态已知,我的意思是与泛型方法或使用类型参数作为返回类型的泛型方法相反).在调用时,编译器隐藏了在CLR级别上返回void的方法与返回真正的unit值的方法之间的区别.

I believe the rule is that a method that is statically known to have return type unit will be compiled to a .NET method with return type void in the .NET type system (by statically known, I mean in contrast to a generic method or a method on a generic type which uses a type parameter as the return type). At invocations, the compiler hides the distinction between methods that return void and methods that return true unit values at the CLR level.

出现示例中的问题是因为正确实现通用接口实际上需要CLR级别的unit返回类型(并且CLR确实关心unitvoid之间的区别).换句话说,仅当您要覆盖通过静态已知返回unit的方法(基于该类型参数替换unit)的方法来返回通用类的类型参数的方法时,才会发生问题. .这里所说的覆盖是指在类或接口上实现抽象方法,或者在类上覆盖非密封方法.

The problem in your example occurs because properly implementing the generic interface actually requires a unit return type at the CLR level (and the CLR does care about the distinction between unit and void). In other words, the problem occurs if and only if you want to override a method which returns a type parameter of a generic class by a method which is statically known to return unit (based on substituting unit for that type parameter). By override here, I mean either implementing abstract methods on classes or interfaces or overriding non-sealed methods on classes.

正如Tamil指出的那样,解决此限制的一种方法是确保使用F#函数而不是方法.另一个解决方法是在层次结构中引入一个额外的具体类,该类具有虚拟泛型类型参数(例如,额外的类为T<'unit>),并在可能导致问题的任何地方返回Unchecked.defaultof<'unit>而不是().然后,您可以从T<unit>派生一个附加的非泛型具体类T,一切都会正常进行.

As Tamil points out, one way to work around this limitation is to ensure that you use F# functions instead of methods. Another workaround is to introduce an extra concrete class into the hierarchy which has a dummy generic type parameter (say the extra class is T<'unit>), and to return Unchecked.defaultof<'unit> instead of () wherever that would cause problems. Then you can derive an additional non-generic concrete class T from T<unit> and everything will work fine.

这篇关于在什么条件下单位是类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆