Statik Olarak Çözümlenmiş Tür Parametreleri

Statik olarak çözümlenen tür parametresi, derleme zamanında yerine gerçek bir türle değiştirilen bir tür parametresidir.

Sözdizimi

'type-parameter

F# sürüm 7.0'a kadar aşağıdaki söz dizimini kullanmak zorunda kaldı

^type-parameter

Açıklamalar

F# dilinde iki farklı tür parametre türü vardır. İlk tür standart genel tür parametresidir. Bunlar, diğer .NET dillerindeki genel tür parametrelerine eşdeğerdir. Diğer tür statik olarak çözümlenir ve yalnızca iç işlevlerde kullanılabilir.

Statik olarak çözümlenen tür parametreleri, öncelikle bir tür bağımsız değişkeninin kullanılabilmesi için belirli bir üyeye veya üyeye sahip olması gerektiğini belirtmenize olanak tanıyan kısıtlamalar olan üye kısıtlamalarıyla birlikte yararlıdır. Normal bir genel tür parametresi kullanarak bu tür bir kısıtlama oluşturmanın hiçbir yolu yoktur.

Aşağıdaki tabloda, iki tür parametresi arasındaki benzerlikler ve farklar özetlemektedir.

Özellik Genel Statik olarak çözüldü
Çözüm süresi Çalıştırma Derleme zamanı
Üye kısıtlamaları Üye kısıtlamalarıyla kullanılamaz. Üye kısıtlamalarıyla kullanılabilir.
Kod oluşturma Standart genel tür parametrelerine sahip bir tür (veya yöntem), tek bir genel tür veya yöntemin oluşturulmasına neden olur. Gereken her tür için bir tane olmak üzere birden çok tür ve yöntem örneği oluşturulur.
Türlerle kullanma Türlerde kullanılabilir. Türlerde kullanılamaz.
Satır içi işlevlerle kullanma Satır içi bir işlev standart genel tür parametresiyle parametrelenemez. Girişler tam olarak genel değilse, F# derleyicisi bunları özelleştirir veya özelleştirmek için hiçbir seçenek yoksa hata verir. Statik olarak çözümlenen tür parametreleri satır içi olmayan işlevlerde veya yöntemlerde kullanılamaz.

Birçok F# çekirdek kitaplığı işlevi, özellikle işleçler, statik olarak çözümlenen tür parametrelerine sahiptir. Bu işlevler ve işleçler satır içidir ve sayısal hesaplamalar için verimli kod oluşturma işlemine neden olur.

İşleçler kullanan veya statik olarak çözümlenen tür parametreleri olan diğer işlevleri kullanan satır içi yöntemler ve işlevler, statik olarak çözümlenen tür parametrelerini de kullanabilir. Genellikle tür çıkarımı, statik olarak çözümlenen tür parametrelerine sahip olmak için bu tür satır içi işlevleri çıkarsar. Aşağıdaki örnek, statik olarak çözümlenmiş bir tür parametresine sahip olduğu sonucuna varan bir işleç tanımını gösterir.

let inline (+@) x y = x + x * y
// Call that uses int.
printfn "%d" (1 +@ 1)
// Call that uses float.
printfn "%f" (1.0 +@ 0.5)

çözümlenen türü (+@) , statik olarak çözümlenen tür parametrelerinde üye kısıtlamalarını çıkarsamak için tür çıkarımına neden olan hem (+)(*)de kullanımını temel alır. F# yorumlayıcısında gösterildiği gibi çözümlenen tür aşağıdaki gibidir.

'a -> 'c -> 'd
when ('a or 'b) : (static member ( + ) : 'a * 'b -> 'd) and
('a or 'c) : (static member ( * ) : 'a * 'c -> 'b)

Çıktı aşağıdaki gibidir:

2
1.500000

Aşağıdaki örnekte yöntemler ve statik yöntemlerle SRTP kullanımı gösterilmektedir:

type Record =
    { Number: int }
    member this.Double() = { Number = this.Number * 2 }
    static member Zero() = { Number = 0 }
    
let inline double<'a when 'a:(member Double: unit -> 'a)> (x: 'a) = x.Double()    
let inline zero<'a when 'a:(static member Zero: unit -> 'a)> () = 'a.Zero()

let r: Record = zero ()
let doubleR = double r

F# 7.0'dan başlayarak aşağıdaki örnekte olduğu gibi kısıtlamayı yinelemek yerine kullanabilirsiniz 'a.Zero() .

F# 4.1'den başlayarak, statik olarak çözümlenen tür parametre imzalarında somut tür adları da belirtebilirsiniz. Dilin önceki sürümlerinde, tür adı derleyici tarafından çıkarılmıştı, ancak imzada belirtilemedi. F# 4.1'den itibaren statik olarak çözümlenen tür parametre imzalarında somut tür adları da belirtebilirsiniz. Aşağıda bir örnek verilmiştir (bu örnekte ^ kullanılacak basitleştirme desteklenmediğinden yine de kullanılması ' gerektiğini unutmayın):

let inline konst x _ = x

type CFunctor() =
    static member inline fmap (f: ^a -> ^b, a: ^a list) = List.map f a
    static member inline fmap (f: ^a -> ^b, a: ^a option) =
        match a with
        | None -> None
        | Some x -> Some (f x)

    // default implementation of replace
    static member inline replace< ^a, ^b, ^c, ^d, ^e when ^a :> CFunctor and (^a or ^d): (static member fmap: (^b -> ^c) * ^d -> ^e) > (a, f) =
        ((^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e) (konst a, f))

    // call overridden replace if present
    static member inline replace< ^a, ^b, ^c when ^b: (static member replace: ^a * ^b -> ^c)>(a: ^a, f: ^b) =
        (^b : (static member replace: ^a * ^b -> ^c) (a, f))

let inline replace_instance< ^a, ^b, ^c, ^d when (^a or ^c): (static member replace: ^b * ^c -> ^d)> (a: ^b, f: ^c) =
        ((^a or ^c): (static member replace: ^b * ^c -> ^d) (a, f))

// Note the concrete type 'CFunctor' specified in the signature
let inline replace (a: ^a) (f: ^b): ^a0 when (CFunctor or  ^b): (static member replace: ^a *  ^b ->  ^a0) =
    replace_instance<CFunctor, _, _, _> (a, f)

Ayrıca bkz.