【问题标题】:F# static member constraints combined with IDisposableF# 静态成员约束结合 IDisposable
【发布时间】:2020-12-20 20:05:35
【问题描述】:

我想实现一个通用 F# 类,它的类型参数肯定提供了一个名为“TryParse”的静态方法。除此之外,我希望我的班级在不再需要后得到正确处理。我想出了以下实现:

type Listener<'a when ^a : (static member TryParse : string -> ^a option)>() =
   // construct the object here
   let input : string = "" // get input
   let res = (^a : (static member TryParse : string -> ^a option) input)

   member this.Start() =
       // ...
       ()

   interface IDisposable with
      member this.Dispose() =
         // do cleanup
         ()

问题是:在两个成员(“开始”和“处置”)上,我收到以下错误:

Error: This code is not sufficiently generic. The type variable  ^a when  ^a : (static member TryParse : string -> ^a option) could not be generalized because it would escape its scope.

我可以通过用“内联”装饰它来修复 Start() 成员,但我无法对接口定义做同样的事情。

是否可以同时强制我的泛型类型来实现静态方法并定义类 Disposable ?

【问题讨论】:

  • 类不能有SRTP,只有函数可以。
  • 有趣的事实:没有 IDisposable 接口并且在“Start”成员中添加了“inline”说明符,Visual Studio 中的类类型检查,但随后出现链接错误。

标签: .net compiler-errors f# type-constraints


【解决方案1】:

如 cmets 中所述,类不能具有静态解析的类型参数。如果你想做这样的事情,一个很好的技巧是有一个内联方法,它具有约束并捕获你以后需要在接口中或作为一等函数的操作。

在您的情况下,您可以更改您的类以将 tryParse : string -&gt; 'a option 作为参数,然后使用静态方法让您自动捕获支持它的类型:

type Listener<'a>(tryParse : string -> 'a option) =
   let input : string = "" 
   let res = tryParse input

   member this.Start() = ()

   interface System.IDisposable with
      member this.Dispose() = ()

具有静态内联成员的非泛型类型将是:

type Listener = 
  static member inline Create< ^b 
      when ^b : (static member TryParse : string -> ^b option)>() = 
    new Listener< ^b >(fun input -> 
      (^b : (static member TryParse : string -> ^b option) input))

假设你有一个类型 Foo 和适当的 TryParse 成员,你可以这样写:

let l = Listener.Create<Foo>()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 2011-01-24
    • 2018-02-26
    • 2011-06-07
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多