【问题标题】:Inline function and type extension内联函数和类型扩展
【发布时间】:2016-04-12 19:02:56
【问题描述】:

假设我有两种不同的类型:

type Foo = { foo : string }
type Bar = { bar : int32 }

我想实现适用于FooBar 实例的通用函数zoo我无法更改 FooBar,因为它们是库代码的一部分。

这是我第一次尝试使用类型扩展和内联函数,如 here 所述:

// Library.fs
module Library

type Foo = { foo : string }
type Bar = { bar : int32 }

// Program.fs
type Foo with
    static member zoo (f : Foo) = "foo"

type Bar with
    static member zoo (b : Bar) = "bar"

let inline zoo (x : ^t) =
    (^t : (static member zoo : ^t -> string) x)

let f = zoo { foo = "1" } // error FS0001: The type 'Foo' does not support the operator 'zoo'

为什么内联函数定义不依赖类型扩展?如何在不更改初始 FooBar 类型定义的情况下解决我的问题?

【问题讨论】:

    标签: f# inline


    【解决方案1】:

    使用方法重载。

    扩展方法的问题在于solving member constraints时没有考虑到它们。

    因此,您可以使用方法重载,如您自己的答案中所示,或者您可以更进一步并通过使用中间类型和中间方法(在本例中为简单起见的运算符)来创建内联泛型函数来解决问题:

    type T = T with
        static member ($) (T, x:Foo) = "foo"
        static member ($) (T, x:Bar) = "bar"
    
    let inline zoo x = T $ x
    
    let f = zoo { foo = "1" }
    

    这里有 more details 了解它的工作原理。

    请注意,此函数将被内联,例如,您将无法从 C# 调用它,如果需要,请不要使用函数,使用简单和标准的方法重载。

    【讨论】:

      【解决方案2】:

      到目前为止我能做到的最好的事情是

      type Ext =
          static member zoo (f : Foo) = "foo"
          static member zoo (b : Bar) = "bar"
      
      let f = Ext.zoo { foo = "1" } // "foo"
      let b = Ext.zoo { bar = 2 } // "bar"
      

      这不是最好的,也不是很通用的解决方案,但至少它有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 2019-11-02
        • 1970-01-01
        • 2019-07-13
        相关资源
        最近更新 更多