2010-02-03 31 views
6

uygulanan vb imzalarlar., bunu buldum F #

type AbsDynamicImplTable<'T>() = 
    let AbsDynamic x   = AbsDynamicImplTable<_>.Result x 

    [<CompiledName("Abs")>] 
    let inline abs (x: ^T) : ^T = 
     AbsDynamic x 
     when ^T : ^T = absImpl x 

Ve bunlarla karıştı: F # Bu uygulamaya ve kaynak kodunda bir arama yaptım nasıl yüzden merak etti.

abs gibi bir işlevde bildiğim gibi, girişi 0 ile karşılaştırmalı ve farklı türler için farklı 0'lar vardır.

Teşekkürler.

+0

X'in mutlak değerini bulmak için 0 ile karşılaştırmanıza gerek yok - bunu -X ile karşılaştırabilirsiniz. – Simon

+1

@Simon iyi bir noktaya benziyor. AMA, yönteminiz doğru değil. X = -2147483648'i düşünün. –

+0

evet, iyi bir nokta - yine de durumun -X'i değerlendirmek için aynı istisnayı aldığına inanıyorum. Gerçek uygulama için – Simon

cevap

13

ChaosPandion, F # işlevleriyle sorundan yayınlanan koda bir açıklama ekleyin. Bunu yalnızca F # /. NET jeneriklerini kullanarak ifade etmenin bir yolu yoktur - desteklenen tek kısıtlama, tip parametresinin belirli bir arabirimi uyguladığı veya bir kurucuya sahip olduğu, ancak sayısal türler için bir kısıtlama olmadığıdır.

Yani, F # da statik kısıtlamaları destekler (tür parametresi yerine 'a zamanki ait ^a olan) ve bu (function inline olmak zorunda neden bu da açıklıyor) inlining kullanılarak derleme sırasında işlenir. böylece, DivideByInt tip DivideByInt üyesi var olmasını gerektirir - kısıtlamaları anlaşılmaktadır ki

> let inline half (num: ^a) : ^a = 
    LanguagePrimitives.DivideByInt< (^a) > num 2 
    ;; 
val inline half : ^a -> ^a 
    when ^a : (static member DivideByInt : ^a * int -> ^a) 

> half 42.0;; 
val it : float = 21.0 

> half 42.0f;; 
val it : float32 = 21.0f 

Not: Bazı kısıtlamalar gerektiren birçok yararlı işlevleri içerir LanguagePrimitives gelen yerleşik işlevleri kullanarak size statik kısıtlamalarıyla kendi işlevini yazabilirsiniz Bizim fonksiyonumuz aynı şeyi gerektirir (ve bu üyeye sahipse kendi türünüzle çalışacaktır, bu da oldukça faydalıdır!). Buna ek olarak

, abs uygulanması sadece F # kütüphanede kullanılabilmektedir iki ek hileler kullanır - bu farklı (when ^a:int = .... kullanarak) farklı türleri için (inlining kullanılacak) kod ve bir geri dönüş davasını belirten hangi Abs üye kullanır, bu nedenle herhangi bir açıkça listelenen türü veya Abs üye ile bir tür çalışacaktır. Başka bir hile, "türü değiştirir", ancak herhangi bir kod içermeyen retype işlevidir - yalnızca amaç kod türü denetimi yapmaktır, ancak bu çok güvensiz olabilir - bu yalnızca F # kitaplıklarında kullanılır.

+0

+1 - Fantastik. – ChaosPandion

8

Aslında bu Abs tablo bu arayacak: abs herhangi bir sayısal türü ile çalışabilmesi gibi

let inline abs_impl (x: ^a) : ^a = 
    (^a: (static member Abs : ^a -> ^a) (x)) 
    when ^a : int32  = let x : int32  = retype x in if x >= 0 then x else -x 
    when ^a : float  = let x : float  = retype x in if x >= 0.0 then x else -x 
    when ^a : float32  = let x : float32 = retype x in if x >= 0.0f then x else -x 
    when ^a : int64  = let x : int64  = retype x in if x >= 0L then x else -x 
    when ^a : nativeint = let x : nativeint = retype x in if x >= 0n then x else -x 
    when ^a : int16  = let x : int16  = retype x in if x >= 0s then x else -x 
    when ^a : sbyte  = let x : sbyte  = retype x in if x >= 0y then x else -x 
    when ^a : decimal  = System.Math.Abs(retype x : decimal) 
+0

+1, ama cevabımın ilk versiyonu doğru sanırım. –