假设我正在构造一个f
带有单个参数的 F# 泛型函数integral
,并且函数语义的这个参数应该被限制为从 到 的任何 .NETSystem.SByte
整数System.Int32
类型System.Numerics.BigInteger
。
一种方法是实施
let inline f (integral: 'a) =
(* function body here *) ...
并依赖编译器推导的约束'a
从 ' 的主体的实际内容派生f
,这可能与 .NET 整体类型集一致,也可能不一致。
另一种方法可能是强制显式手动选择先验约束,'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 *)()
所以f 1uy
, f 1L
,f 1I
马上通过静态类型检查,但是f 'a'
, f 1.0
,f 1m
没有。
如果有的话,使用第二种方法比第一种方法有什么好处?
有没有更惯用的方法来达到最初的目标?
更新 2014年 2 月 3日具有讽刺意味的是,仅在今天查看此答案后,才设法从@kvb 的提示中获取了工作代码:
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