2013-04-19 22 views
7

Neden fail değeri bir istisna atar? fine değeri çalışır. inline'u kaldırırsam veya 't'u float'a dönüştürürsem çalışır.Yapıdaki Inline plus operatörü bir istisna atar (F #)

[<Struct>] 
type Test<'t> = 
    val x: 't 
    val y: 't 
    new (x,y) = { x = x; y = y } 

    static member inline (+) ((x,y), a: _ Test) = 0 
    static member inline (-) ((x,y), a: _ Test) = 0 

let a = 1.,2. 
let b = Test(1.,2.) 
let fine = a - b 
let fail = a + b 

hata iletisi:

işlenmeyen durum: System.TypeInitializationException: tür başlatıcısı fo r 'AdditionDynamicImplTable 3' threw an exception. ---> System.NotSupportedExcep tion: Dynamic invocation of op_Addition involving coercions is not supported. at [email protected][a,b,c](Type aty, Type bt y, Unit unitVar0) at Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamicImplTable 3..cctor () --- iç durum yığın izleme sonu - - Microsoft.FSharp.Core.LanguagePrimitives.AdditionDynamic [T1, T2, TResult] (T1 x, T2 y) de $ Program.main @() C: \ Kullanıcılar \ olsv \ Docume nTS \. Visual Studio 2012 \ Projects \ Consol eApplication1 \ ConsoleApplication1 \ Program. fs: satır 14 Devam etmek için herhangi bir tuşa basın. . .

cevap

5

Bu derleyicisi hata benziyor - veya (microsoft nokta com de fsbugs de lütfen bildirin) bir şey eksik. Herhangi bir nedenle, derleyici + operatörüne çağrıyı başarısızlıkla sonuçlandırıyor (- ve / için çalışıyor ve +. gibi özel işleçler için, ancak + ve * için başarısız oluyor).

// Inlined - returns zero directly 
fine = 0; 

// Failed to inline - calls a version which used dynamic lookup 
fail = LanguagePrimitives.AdditionDynamic 
     <Tuple<double, double>, Test.Test<double>, double>(a, b); 

AdditionDynamic yöntem zamanında iki tip için + bir uygulamayı bulmak üzere bazı iç tablosu kullanır:

Bu derleyici aslında böyle bir şey üretir demektir. Buradaki türünüzü kaydettirebilmenize rağmen, gerçekten işe yaramazdı, çünkü davetler yavaş olurdu.

ben gerçekten buna hiç hoş çözüm bulamadık - sadece bazı temel sayısal türleri (float, int vs.) için operatöre gerekiyorsa o zaman en kolay seçenek sadece burada inline kullanmaktan kaçınmak ve tanımlamak olabilir (bir belirli türleri için aşırı) operatörü:

static member (+) ((x:float,y:float), a: float Test) = x + y + a.x + a.y 

Ayrıca küresel operatör ve farklı aşırı yükleme uygulayan bir yardımcı türü ile hile deneyebilirsiniz, ancak bu yardım edecek emin değilim: bakınız örneğin , this past question.

İlgili konular