我尝试编写一个对算术类型进行泛型转换的函数,例如,一个函数接收类型为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] 删除。
我来说两句