F# 类型推断创建不需要的约束

F# 类型推断创建不需要的约束,f#,type-inference,F#,Type Inference,由于我有大量的IDisposables需要处理,因此我设置了一个一次性物品列表和一个传递函数,以向其中添加物品作为副作用: let mutable disposables = [] let (~-) (x:'a) = disposables <- x :: disposables; x 问题是F#会自动将'a约束为IDisposable,并显示警告消息: 此构造导致代码不像类型注释所指示的那样通用。类型变量“a”已被约束为类型“IDisposable” 因此,operator~-的返回类

由于我有大量的
IDisposable
s需要处理,因此我设置了一个一次性物品列表和一个传递函数,以向其中添加物品作为副作用:

let mutable disposables = []
let (~-) (x:'a) = disposables <- x :: disposables; x
问题是F#会自动将
'a
约束为
IDisposable
,并显示警告消息:

此构造导致代码不像类型注释所指示的那样通用。类型变量“a”已被约束为类型“IDisposable”

因此,
operator~-
的返回类型变为IDisposable,这破坏了函数的便利性

有没有办法阻止F#创建此约束?

明白了

答案是当我在函数中使用它时,而不是在函数的类型签名中,将
x
向上转换为
IDisposable

let mutable disposables = []
let (~-) x = disposables <- (x :> IDisposable) :: disposables; x
let可变一次性用品=[]
let(~-)x=可处置的):可处置的;x

您没有征求关于代码的一般建议,但我觉得有必要指出一些奇怪之处

首先,您几乎不必调用
Dispose()
<代码>使用是管理资源的标准方式。您可能应该这样做:

use thing1=新表单()
使用thing2=新控件()
其次,为什么要将一个不可变的数据结构分配给一个
mutable
变量?如果您确信需要手动跟踪资源,请使用

let disposables = ResizeArray<IDisposable>()
let disposables=ResizeArray()

最后,在定义一个在其自身范围之外变异变量的运算符之前,您应该仔细考虑。这对于操作员来说是不寻常的行为(除非操作员的范围很窄)。

如果
一次性用品
IDisposable
的列表,那么
x
除了
IDisposable
本身之外还能是什么?在任何情况下,您可能会给
disposables
一个显式类型,看看您得到了什么——我是Haskeller,所以这只是猜测。如果执行
let inline(~-)(x:'a)=disposables@JohnPalmer Nope,
本地类绑定不能标记为inline。考虑将定义从类中提升,或者不要将其标记为内联。@ JONPURDY,我需要返回的<代码> x>代码>是我发送的类型,而不是<代码> IDISPOSTABLE < /代码>。在
一次性用品上注释一个类型似乎变化不大:(有更好的方法做这件事!
(向上播放x)
(x:>IDisposable)读起来要好一点)
IMO,但您需要为
一次性用品
提供一个显式类型。虽然我很想使用
use
,但我正在编写游戏代码,因此不可避免地我必须使用.NET Framework的本机习惯用法才能提高效率,特别是为了避免调用GC过多。我经常使用类,因为闭包允许就使用列表而言,我并不介意开销太大,因为一次性资源大多是巨大的资源,我无论如何也不会创建很多,所以列表和ResizeArray之间没有任何实际区别。
let disposables = ResizeArray<IDisposable>()