TLDR:如何在F#中重复/传播静态类型参数?对于下面的示例函数,我无法使其工作。
这是一个最小的(我认为)版本,它举例说明了我想要实现的目标(即,一种基于静态已知的MinValue
和MaxValue
属性存在来测试值范围的方法在类型上):
type MyByte = MyByte of byte with
static member MinValue = MyByte Byte.MinValue
static member MaxValue = MyByte Byte.MaxValue
static member op_Explicit (MyByte x): int64 = int64 x
static member op_Explicit (MyByte x): double = double x
let inline isWithinMinMaxRange< ^b, ^a when
^b: comparison
and ^a: comparison
and ^b: (static member MinValue: ^b)
and ^b: (static member MaxValue: ^b)
and ^b : (static member op_Explicit: ^b -> ^a) >
(value: ^a) =
let minRange = ((^b) : (static member MinValue: ^b) ())
let maxRange = ((^b) : (static member MaxValue: ^b) ())
let cast v = (^b : (static member op_Explicit: ^b -> ^a) v)
value > cast minRange && value < cast maxRange
// works as can be expected
let test() = isWithinMinMaxRange<MyByte, _> 256.0
// does not work, complains it cannot convert to 'a
let inline test2 v = isWithinMinMaxRange<MyByte, _> v
上面的代码在test2
上抛出了编译错误:
错误FS0043:“MyByte”类型不支持转换为“a”类型
所以这里的问题是:如何说服编译器我们有这样的转换?当我添加一个抛出的泛型虚拟函数时,它会编译,但编译器然后总是转到该泛型虚函数,无法解析选择具有适当具体类型的方法
如果我尝试通过重复约束来解决这个问题,它会变得更奇怪(并且可读性更低):
let test< ^source, ^value
when ^source: comparison
and ^value: comparison
// next line is redundant, but shows my experiments ;)
and (^source or ^value) : (static member op_Explicit: ^value -> ^source)
and ^source: (static member op_Explicit: ^source -> MyByte)
and ^value: (static member op_Explicit: ^value -> sbyte)
and ^source: (static member MinValue: ^source)
and ^source: (static member MaxValue: ^source)> (v: ^value) =
isWithinMinMaxRange< ^source, ^value> v
这会产生不祥的错误:
错误FS0001:类型参数缺少约束'当^ source :(静态成员op_Explicit:^ source - &gt; ^?9104)'
和
错误FS0043:类型参数缺少约束'当^ source :(静态成员op_Explicit:^ source - &gt; ^?9104)
我的直觉是,不知何故编译器无法静态地找出正确的类型,所以我尝试了我的技巧书中的各种变体,但过了一段时间,并逐一修复每个“如此错过如此约束”的错误,我一直以上面的错误结束。
任何帮助都非常感谢这些:
^?9104
背后的类型是什么(我的主项目给出了不同的数字)?