2016-06-18 45 views
9

我试图如下定义一个更一般的情况下为(!)运算符的内联函数,F#调用带有类型变量

let inline (!) (cell : ^a) = 
    (^a : (member Value : ^b) cell) 

因此,它不仅适用于ref类型,但任何类型的一Value的成员。

> !(ref 10) ;; 
val it : int = 10 

> !(lazy 5) ;; 
val it : int = 5 

但是,当我试图把它与类型变量适用于一个类型出现问题,

> let getValue (c : 'a ref) = !c ;; 

    let getValue (c : 'a ref) = !c ;; 
    ------------------^^ 

C:\Users\User\AppData\Local\Temp\stdin(6,19): warning FS0064: This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'obj'. 

val getValue : c:obj ref -> obj 

同时,如果我扩大了内联函数工作正常。

> let getValue (c : 'a ref) = c.Value ;; 

val getValue : c:'a ref -> 'a 

任何人都知道为什么会发生这种情况?谢谢。

回答

5

由于您的getValue函数不是内联函数,因此约束条件不起作用。

问题是.NET类型系统无法存储F#可以在inline中使用的约束类型。

因此,当你有一个非内联函数以这种方式使用内联函数时,你会得到一个错误。

+0

'getValue'的后一个版本只是前一个版本的手动扩展,但我知道我可能在这里丢失了一些东西,但我仍然无法看到前者如何引入更多的类型约束,而.NET可以不会被捕获。 – Doaz

+0

我认为'getValue'上的约束是'!'上约束的超集。由于getValue约束条件需要内联,因此它不能是非内联函数 –