F#中的算术转换为泛型

塔清定(Ta Thanh Dinh)

我尝试编写一个对算术类型进行泛型转换的函数,例如,一个函数接收类型为type的参数uint64,然后转换为与type参数相同的类型。我的想法是:

let convert<'T> (x:uint64) = 'T x

但是这段代码无法编译,在尝试了几种方法后,我就停留在这里:

let convert<'T> (x:uint64) = 
  match Unchecked.defaultof<'T> with 
    | :? uint32 -> uint32 x
....

那么我该如何在F#中编写这样的泛型算术转换呢?(我刚刚开始学习,所以我的问题可能很愚蠢,请放心)。

古斯

您可以使用静态成员约束,这是一个“简短”的示例:

type Explicit =
    static member inline ($) (_:byte , _:Explicit) = byte            
    static member inline ($) (_:sbyte, _:Explicit) = sbyte           
    static member inline ($) (_:int16, _:Explicit) = int16           
    static member inline ($) (_:int32, _:Explicit) = int
    // more overloads

let inline convert value: 'T = 
    (Unchecked.defaultof<'T> $ Unchecked.defaultof<Explicit>) value

// Specialized to uint64
let inline fromUint64 (value: uint64) :'T = convert value

// Usage
let x:int = fromUint64 7UL

如注释中所述,您可以使用F#+中的函数explicit该函数涵盖存在显式运算符的所有情况。这是一个示例代码

现在,如果您查看在另一个项目(FsControl)中定义的该函数源代码,您会发现更加复杂的解决方法。

您可能想知道为什么,所以这是一个很长的答案:

从理论上讲,应该可以使用单个调用该成员的调用op_Explicit,但这仅在该成员确实存在时才起作用,而本机数字类型则不是这种情况。

对于这些情况,F#编译器使用通常称为“模拟成员”的功能,该功能是通过静态优化实现的,但在F#编译器源代码之外不可用。

因此,F#+使用了另一种功能:重载解析,如我在示例代码中向您展示的,但是对于那些真正包含op_Explicit静态成员的成员,它通常使用额外的重载

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章