F#中的静态解析类型参数未按预期解析,或者:无法传播类型参数?

时间:2017-08-26 01:40:55

标签: compiler-errors f# type-parameter

TLDR:如何在F#中重复/传播静态类型参数?对于下面的示例函数,我无法使其工作。

这是一个最小的(我认为)版本,它举例说明了我想要实现的目标(即,一种基于静态已知的MinValueMaxValue属性存在来测试值范围的方法在类型上):

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背后的类型是什么(我的主项目给出了不同的数字)?
  • 为什么不能传播这些类型约束?根据我的经验,通常复制约束可以解决任何和所有问题,除非方法以更具体的方式使用,解决它们。但即使我在两个函数上使约束条件完全相同,也会出现相同的错误错误。

0 个答案:

没有答案
相关问题