2010-07-09 70 views
12

任何人都可以解释为什么下面的第二个例子不会编译?为什么'代码不够通用'?

'测试2'给出了“错误FS0670:该代码不够通用,类型变量^ a不能泛化,因为它会逃避它的范围。”我无法理解此错误消息。

// Test 1 
type test1<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> a.ToString() 

// Test 2 
type test2<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> string a 

// Test 3 
type test3<'a> = | A of 'a 
    with 
    override t.ToString() = 
     match t with 
     | A a -> string (a :> obj) 

回答

5

这里的另一个摄制:

let inline f< ^T>(x:^T) = box x 

type test4<'a> = | A of 'a 
    with 
    member t.M() = 
     match t with 
     | A a -> f a 

string是使用静态类型约束的内联函数,以及这种功能的错误诊断有时很差。我不太了解诊断消息本身,但重要的是,在呼叫站点,我们不知道通用类型'a,这意味着我们无法将呼叫的正确版本内嵌到string(或f我的repro)。在例如如果您转播到obj,我们知道我们想要嵌入obj版本的string,这样就可以。

0

我想这是因为字符串有(OBJ - >串)的签名,以便利用其自己的字符串迫使一个是类型obj的。 (F#不做隐式转换。)

+1

'string' [事实上是'T - > string'](http://msdn.microsoft.com/en-gb/library/ee340491.aspx),所以这应该在理论上工作。尽管我没有更好的解释。 – 2010-07-09 09:22:41

+0

哦,是的,我只是卡住了字符串;;到F#交互式来获取类型。 推测实际上使用字符串是强制编译强制输入类型,它选择obj作为最低公分母? – Massif 2010-07-09 09:56:48