假设我正在构造一个带有单个参数 integral
的 F# 泛型函数 f
,并且函数语义的该参数应限制为任何 .NET 整数类型从 System.SByte
到 System.Int32
到 System.Numerics.BigInteger
。
一种方法是实现
let inline f (integral: 'a) =
(* function body here *) ...
并依赖于从 f
主体的实际内容派生的编译器推导的对 'a
的约束,该约束可能与整套整型一致,也可能不一致。网
类型。
另一种方法可能是强制对 'a
显式手工选择先验约束,这将真正保证已知的 .NET 类型只有整型类型传递静态
例如检查
let inline f (integral: ^a when ^a:(static member (|||): ^a * ^a-> ^a)) =
(* function body here, unit for illustration *)()
或
let inline f< ^a when ^a : (static member (|||): ^a * ^a -> ^a)> (integral: ^a) =
(* function body here, unit for illustration *)()
so f 1uy
、f 1L
、f 1I
立即通过静态类型检查,但 f 'a'
、f 1.0
、f 1m
没有。
使用第二种方法相对于第一种方法有什么好处(如果有的话)?
是否有更惯用的方法来实现最初的目标?
更新 02/03/2014 讽刺的是,直到今天才查看 this answer设法从 @kvb's prompt 中获取工作代码:
let inline implementation integral = ((* whatever implementation here *))
type Integral = Integral with
static member ($) (Integral, value: byte) = implementation value
static member ($) (Integral, value: sbyte) = implementation value
static member ($) (Integral, value: int16) = implementation value
static member ($) (Integral, value: uint16) = implementation value
static member ($) (Integral, value: int) = implementation value
static member ($) (Integral, value: uint32) = implementation value
static member ($) (Integral, value: int64) = implementation value
static member ($) (Integral, value: uint64) = implementation value
static member ($) (Integral, value: bigint) = implementation value
let inline doit integral = Integral $ integral
doit 1
doit 1I
doit 1.0 // does not compile
doit 1.0m // does not compile
doit '1' // does not compile
最佳答案
如果您确实只想将可能性限制为整数类型,那么使用重载静态方法将是一种选择。为了减少代码重复,这些都可以通过不受限制的通用函数来实现。
关于generics - 将 F# 泛型函数参数约束为整型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16737675/