当方法参数为单位时,F# 无法使用对象表达式实现接口

F# can't implement interface with object expression when method parameter is unit

当它包含一个没有类型的方法时,我找不到用对象表达式实现接口的方法,而这些类型可以引用正在实施的类型。签名为 unit -> string 的方法是一个简单的示例。示例代码如下:

type AsString =
    abstract member asString: unit -> string
    
type AsString2<'T> =
    abstract member asString: 'T -> string

type SomeDu =
    | A of int
    | B of string
    | C of float
    interface AsString
        with member self.asString () =
                match self with
                | A a -> string a
                | B b -> b
                | C c -> string c
    interface AsString2<SomeDu>
        with member self.asString x =
                if not (x = self) then failwith "argument must be the member container"
                match self with
                | A a -> string a
                | B b -> b
                | C c -> string c

//this expression was expected to have type AsString but here has type SomeDU            
let implSomeDU = 
    {new AsString with
        member self.asString () =
            match self with
            | A a -> string a
            | B b -> b
            | C c -> string c}

如果我像 AsString2 那样尝试引用实现类型,那么对象表达式没有问题,但 DU 上的实现现在有一个我无法在类型系统中表达的要求: 参数必须是 DU 实例或方法没有值。

有什么技巧可以让我实现 AsString 作为 SomeDu 的对象表达式吗?

当使用对象表达式实现接口时,this 的类型始终是接口,而不是其他任何东西 - 不像在其他类型中实现接口(其中 this 指的是到当前值),在对象表达式的情况下,“当前值”只是接口实现。

如果您想在现有类型中实现接口,请在类型本身中实现它。

如果您想获得基于某个其他值的接口的实现,您可以编写一个函数来获取该值并使用对象表达式实现该接口。

在你的例子中,你的函数在第二种情况下看起来像这样:

type AsString =
  abstract member asString: unit -> string

type SomeDu =
  | A of int
  | B of string
  | C of float

let implSomeDU someDu = 
  { new AsString with
      member self.asString () =
          match someDu with
          | A a -> string a
          | B b -> b
          | C c -> string c }