SRTP kısıtlamaları için uzantı üyeleri

Statik olarak çözümlenen tür parametrelerine sahip satır içi bir işlev, belirli bir ada ve imzaya sahip bir üye gerektirebilir. F# 11.2, tür başka bir derlemeden geldiğinde bile kapsam içi uzantı üyesinin bu gereksinimi karşılamasını sağlar.

Belirli türler için bir genel algoritmayı bağdaştırıcılardan ayırmak için bu özelliği kullanın. Bu türleri sarmalamanız veya bunlara nominal arabirim eklemeniz gerekmez.

Note

.NET 11.0.100 SDK'sında, derleyicinin uzantıları çözümlediği yeri etkinleştirin<LangVersion>preview</LangVersion>. Planlanan özellik bandı için bkz. F# 11.2 dil ayarları . Yol ve eşleme örnekleri F# 11.0 kitaplığını ve önizleme tüketicisini kullanır; Bkz . Kitaplıkları ve tüketicileri derleme.

Paylaşılan algoritma için özellik uyarlama

Aşağıdaki uygulama kodu, mevcut iki çerçeve türüyle temsil edilen yolları ölçer. Her iki yol da uzunluğuna 8sahiptir:

open System.Numerics
open Structural.Adapters
open Structural.Algorithms

let complexRoute =
    [ Complex(0.0, 0.0); Complex(3.0, 4.0); Complex(6.0, 4.0) ]
let vectorRoute =
    [ Vector2(0.0f, 0.0f); Vector2(3.0f, 4.0f); Vector2(6.0f, 4.0f) ]

printn (pathLength complexRoute) // 8
printn (pathLength vectorRoute)  // 8

Kitaplık kaynağı ve Structural.Algorithmsöğesini tanımlarStructural.Adapters. Bağdaştırıcılar, farklı yerel API'lere sahip türlerde aynı koordinat özelliğini kullanıma sunar:

type System.Numerics.Complex with
    member point.Coordinates = point.Real, point.Imaginary

type System.Numerics.Vector2 with
    member point.Coordinates = float point.X, float point.Y

Algoritma, kayan Coordinates nokta değerleri çifti döndüren bir özellik ister:

let inline coordinates (point: ^Point) : float * float =
    (^Point : (member Coordinates: float * float) point)

let inline pathLength (points: ^Point list) =
    points
    |> List.pairwise
    |> List.sumBy (fun (a, b) ->
        let ax, ay = coordinates a
        let bx, by = coordinates b
        let dx, dy = bx - ax, by - ay
        sqrt (dx * dx + dy * dy))

Her somut çağrıda, derleyici kısıtlamanın tanığı olarak adlandırılan bir Coordinates üye seçer. Satır içi algoritma bir iç veya uzantı özelliğini kabul eder; boş ve tek noktalı yolların uzunluğu sıfırdır.

Bir işlemi koleksiyon türleri arasında paylaşma

Uzantı kısıtlamaları statik üyeleri de destekler. Kitaplığın Structural.Adapters modülü, mevcut List.map ve Option.map işlevlerini kullanarak bağdaştırıcıları tanımlar:

type List<'T> with
    static member Map(source: 'T list, mapping: 'T -> 'U) : 'U list =
        List.map mapping source

type Option<'T> with
    static member Map(source: 'T option, mapping: 'T -> 'U) : 'U option =
        Option.map mapping source

Kitaplığın Structural.Algorithms modülünde, tam giriş türünde bir Map üye isteyin:

let inline map (mapping: 'T -> 'U) (source: ^Input) : ^Output =
    (^Input :
        (static member Map: ^Input * ('T -> 'U) -> ^Output)
        (source, mapping))

Uygulama daha sonra bir dönüşümü paylaşabilir, öğe türünü değiştirebilir ve iç içe geçmiş bir koleksiyon üzerinde eşleme oluşturabilir:

let inline cleanNames values =
    map (fun (name: string) -> name.Trim().ToUpperInvariant()) values

let batch: string list = cleanNames [ " Ada "; " grace " ]
let optional: string option = cleanNames (Some " linus ")
let missing: string option = cleanNames (None: string option)
let lengths: int list = map String.length batch
let nested: int option list = map (map String.length) [ Some "abc"; None ]

printfn "%A; %A; %A" batch optional missing
printfn "%A; %A" lengths nested
// ["ADA"; "GRACE"]; Some "LINUS"; None
// [3; 5]; [Some 3; None]

Derleyici, arabirimleri veya eşleme yasalarını değil üye adlarını ve türlerini denetler. Bu daha yüksek türe sahip bir polimorfizm değildir: hiçbir parametre gibi F<_>bir kapsayıcı oluşturucuyu temsil eder.

İşleç uzantıları

İşleçler aynı mekanizmayı kullanabilir. Örneğin, listeler ve seçenekler için bir eşleme işleci tanımlayın:

type List<'T> with
    static member (|>>) (source: 'T list, mapping: 'T -> 'U) =
        List.map mapping source

type Option<'T> with
    static member (|>>) (source: 'T option, mapping: 'T -> 'U) =
        Option.map mapping source

let inline (|>>) (source: ^Input) (mapping: 'T -> 'U) : ^Output =
    (^Input :
        (static member (|>>): ^Input * ('T -> 'U) -> ^Output)
        (source, mapping))

Bir tüketici açılır StructuralOperators ve işlecini kullanır:

open StructuralOperators

let incremented: int list = [1; 2; 3] |>> ((+) 10)
let length: int option = Some "hello" |>> String.length
// [11; 12; 13] and Some 5

Yerleşik ilkel işleç çözümleri, eşleşen türler için önceliği korur. Uzantı rastgele karma sayısal genişletme sağlamaz veya tüm yerleşik işleçleri değiştirmez.

F# 11.0 modu, FS1215 ile normal bir uzantı işleci bildirimini kabul edebilir, ancak bunu SRTP çözümü olarak kullanamaz. İşleç projesi önizlemeyi kullanır.

Tanımlama grubu işleçleri ve bağlamı

Bir gözlem koleksiyonu ve bağımsız olarak birikmiş bir sonuç çifti aynı kombinasyon protokolüne katılabilir. Aşağıdaki tüketici, kitaplığın bağdaştırıcılarını açtıktan sonra genel algoritmasını tanımlar:

open Composition.Adapters
open Composition.Algorithms

let inline combineAll (batches: ^T list) : ^T =
    List.reduce (++) batches

let observations = combineAll [["temperature"]; ["pressure"; "humidity"]]
let summary = combineAll [(2, ["temperature"]); (3, ["pressure"; "humidity"])]

printfn "%A" observations
printfn "%A" summary
// ["temperature"; "pressure"; "humidity"]
// (5, ["temperature"; "pressure"; "humidity"])

Bu kitaplık uzantıları işlecine tamsayılar, listeler ve çiftler için bir anlam verir:

type System.Int32 with
    static member (++) (left: int, right: int) = left + right

type List<'T> with
    static member (++) (left: 'T list, right: 'T list) = left @ right

type ('T1 * 'T2) with
    static member inline (++) ((a, b), (c, d)) = (a ++ c, b ++ d)

combineAll , kullandığından List.reduceboş bir liste gerektirir. İşlem liste sırasını korur; derleyici, ilişkilendirmeyi zorlamaz veya boş bir giriş için kimlik sağlamaz.

Yerel üst bilgiler type ('T1 * 'T2) with ve type struct ('T1 * 'T2) with CLR başvuru ve değer demetlerini genişletme. Her ikisi de F# 11.2 özellikleridir ve iki ile yedi arasında öğeyi destekler; daha büyük üst bilgiler FS3915 üretir.

Tanımlama kümeleri bir değerin yanı sıra bağlamı da taşıyabilir. Aşağıdaki işleç bağlamsal bir işlev uygularken bir iz ekler:

let priced =
    (["catalogue price"], fun units -> decimal units * 12m)
        <*> (["validated quantity"], 3)

printfn "%A" priced
// (["catalogue price"; "validated quantity"], 36M)
type ('Context * 'Value) with
    static member inline (<*>) ((before, mapping), (after, value)) =
        (before ++ after, mapping value)

type struct ('Context * 'Value) with
    static member inline (<*>) (struct (before, mapping), struct (after, value)) =
        struct (before ++ after, mapping value)

Demet noktalı örnek çağrıları ve gibi type ('a -> 'b) with yerel işlev türü üst bilgileri desteklenmez.

Hem oluşturma kitaplığı hem de tüketici önizlemeyi kullanır. Tüketicide tutun combineAll : Bu azaltmayı dışarı aktarmak tanımlama grubu ++için FS0193 üretebilir. Ayrı yol ve eşleme örnekleri algoritmalarını dışarı aktarır.

Geri dönüşlü inşaat

Kapsayıcıya düz bir değer getiren bir işlem için çıkış türü, hangi üyenin bunu oluşturması gerektiğini belirleyebilir:

type List<'T> with
    static member Return(value: 'T) : 'T list = [value]

type Option<'T> with
    static member Return(value: 'T) : 'T option = Some value
let inline singleton (value: 'T) : ^Output =
    (^Output : (static member Return: 'T -> ^Output) value)
let oneBatch: string list = singleton "ready"
let oneOptional: string option = singleton "ready"
// ["ready"] and Some "ready"

Tüketicinin sonuç ek açıklaması, çıkış türünün Return uzantısını seçer. Tek başına giriş bir kapsayıcı seçemez.

Her kapsayıcı kendi üyesini sağlar. Tek bir türdeki yalnızca dönüş aşırı yüklemeleri için ayrı AllowOverloadOnReturnType özniteliği kullanın.

Kitaplıkları ve tüketicileri derleme

Dil ayarları, başvurular aracılığıyla geçişli olarak değil proje başına uygulanır. Aşağıdaki matris, F# 11.2 özellikleri için .NET 11.0.100 SDK ayarlarını kullanır:

Kitaplık uygulaması Tüketici kullanımı Önizleme gereksinimi
Yerel tanımlama grubu uzantısı üst bilgilerini bildirir. Uzantı işleçlerini çözümler. Her ikisi de önizlemeye ihtiyaç duyar; yeni üst bilgi söz diziminin kendisi önizlemedir.
Normal uzantıları tanımlar ve çözümlenmemiş bir satır içi üye kısıtlamasını dışarı aktarır. Uzantıları bu kısıtlamayı çözen somut türler sağlar. Tüketicinin önizlemeye ihtiyacı var. Kitaplık F# 11.0 kullanabilir.
Dahili olarak bir uzantı kısıtlamasını çözer ve normal veya zaten çözümlenmiş bir satır içi API'yi kullanıma sunar. Bu API'ye daha fazla uzantı çözümlemesi olmadan çağrılar. Kitaplığın önizlemesi gerekiyor; tüketici F# 11.0 kullanabilir.
Uzantıları çözer ve tüketicinin uzantılar aracılığıyla çözümlediğini kısıtlamaları dışarı aktarır. Kalan kısıtlamaları çözer. Her ikisinin de önizlemeye ihtiyacı vardır.

Yol ve eşleme kitaplığı kullanır 11.0; tüketicisi kullanır preview. Tüketici dizininden destekleyen bir F# 11 SDK'sı ile çalıştırın dotnet run .

Derlemeler arasında uzantı kapsamı

Bağımlı satır içi işlevleri tanımlamadan önce genel uzantıları kullanın ve modülünü açın. İçeri aktarılmış çözümlenmemiş bir kısıtlama için, bağdaştırıcıları tüketicide de açın; yapımcının open bildirimleri aktarılamaz. Zaten çözümlenmiş bir API, tüketicinin bağdaştırıcılarını yeniden açmasını gerektirmez.

Çıkarım ve imzalar

F# 11.2 çözünürlüğü, F# 11.0 modunun daha önce yaptığı bazı seçimleri geçersiz kılar. Alıcıyla DateTime tanımlanan bir satır içi yardımcıyı düşünün:

let inline shift (date: System.DateTime) offset = date + offset

F# 11.0 modunda, bu form çıkarabilirsiniz DateTime -> TimeSpan -> DateTime. F# 11.2 uzantı çözünürlüğü etkinleştirildiğinde, için (DateTime or ^Offset) : (static member (+) : DateTime * ^Offset -> ^Result)bir kısıtlamayı koruyabilir. Tüketici daha sonra farklı bir uzaklık türü için genel, kapsam içi bir uzantı seçebilir.

Tüketici, F# 11.0 kitaplığında kaybolan genelliği kurtaramaz. Dışarı aktarılan imzaları denetleyin; üreticinin F# 11.2 çıkarımının da etkinleştirilmesi gerekebilir.

Önizleme sınırlamaları ve sorun giderme

  • FS0001 veya FS0193 için dil ayarlarını, genel görünürlüğü ve bağdaştırıcı kapsamını denetleyin.
  • Sonraki bir üretici dosyası için Complexyol örneğini çözümlerse, kod oluşturma işlemi FS0971, Undefined value 'get_Coordinates'ile başarısız olabilir. Bu çözümü tanımlarıyla veya ayrı bir tüketicide tutun.
  • Rakip bağdaştırıcılar üye seçimini belirsiz hale getirebiliyor.

Ayrıca bkz.