F# 11 の新機胜

F# 11ぞようこそ。 このリリヌスにより、ドメむン モデルを明確に区別し、汎甚アルゎリズムを再利甚し、非同期凊理を調敎し、コンパむラのメモリ䜿甚量を削枛できるようになりたす。

これらの倉曎の背埌にある提案、実装、レビュヌ、テストに぀いお F# コミュニティに感謝したす。 以䞋の特集には、共同䜜成者のリンクが掲茉されおいたす。

Note

これらのサンプルを実行するには、F# 11 コンパむラず、蚘茉された機胜を備えた FSharp.Core 11 が必芁です。 .NET 11.0.100 SDK では、F# 11.2 の機胜には <LangVersion>preview</LangVersion> が必芁です。蚀語蚭定ず蚈画された SDK のサポヌトを参照しおください。 runtime-async のサンプルには远加のランタむム芁件がありたす。以前のバヌゞョンの .NET 11 SDK だけでは、すべおの倉曎が含たれおいない可胜性がありたす。

レコヌド スプレッド: 反埩的なマッピングを䌎わない区別されたモデル

ストレヌゞ モデルずアプリケヌション モデルを区別するために、レコヌド スプレッドは宣蚀を繰り返さずに共有フィヌルドを再利甚したす。 ここでは、モデルは顧客の詳现を共有したすが、さたざたな識別子の皮類を䜿甚したす。

open System

type CustomerId = CustomerId of Guid

type CustomerDetails = { Name: string; PreferredLanguage: string }

type CustomerRow =
    { ...CustomerDetails
      Id: string
      InternalNote: string }

type Customer =
    { ...CustomerDetails
      Id: CustomerId }

...CustomerDetails はフィヌルドの宣蚀を远加したす。 境界では、...row は倉換が識別子を解析する間、倀をコピヌしたす。

let toCustomer (row: CustomerRow) =
    match Guid.TryParse row.Id with
    | true, id -> Ok ({ ...row; Id = CustomerId id }: Customer)
    | false, _ -> Error "Invalid customer identifier."

送信先は共有の詳现を保持し、Idを眮き換え、InternalNoteを陀倖したす。 Guid.TryParse (スプレッドではありたせん) が識別子を怜蚌し、圢匏が正しくない入力が Error を生成したす。

これはアプリケヌション局マッピングの問題に察凊したす。 倀のスプレッドでは、名前付きレコヌドず匿名レコヌドも組み合わせられたす。型スプレッドでは、名前付きレコヌドのみが䜜成されたす。 埌のフィヌルドが優先され、゜ヌスは順番に 1 回実行されたす。 合成の䟋や、共有された芁玠が同時に倉曎、進化するこずに䌎うリスクに぀いおは、レコヌド スプレッド オペレヌタヌを参照しおください。

スプレッドのレコヌドを提䟛いただいた @brianrourkeboll さんに感謝したす。

ゞェネリック アルゎリズム、挔算子、タプルの拡匵メンバヌ

既存の型間でアルゎリズムを共有するために、F# 11.2 では 、拡匵メンバヌが静的に解決された型パラメヌタヌ (SRTP) 制玄を満たすこずができたす。 たずえば、1 ぀の倉換で、ラッパヌ型のないリストずオプションを凊理できたす。

Note

.NET 11.0.100 SDK では、拡匵子が解決される堎所で <LangVersion>preview</LangVersion> を有効にし、そのモゞュヌルを開きたす。 ラむブラリの芁件を参照しおください。

リストずオプション間で倉換を共有する

ラむブラリの map がスコヌプ内にある堎合、アプリケヌションはどちらの衚珟もクリヌンアップしたり、芁玠の型を倉曎したり、倉換を組み合わせたりするこずができたす:

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]

Structural.Adaptersのアダプタヌは、新しいコンテナヌを適甚するのではなく、䜿い慣れた操䜜を䜿甚したす。

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

Structural.Algorithms の共有関数は、静的メンバヌ Map の入力型を問い合わせたす:

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

^Input ず ^Output は静的に解決される型です。 コンパむラは、各具象呌び出しで、必芁な眲名を持぀メンバヌを遞択したす。 これらの拡匵機胜は、むンタヌフェヌスの実装を远加するものではありたせん。 アプリケヌション党䜓は、䞡方のモゞュヌルを開きたす。

挔算子、コンテキスト、および出力の皮類

同じメカニズムで、 タプル挔算子ずコンテキスト䌝達 ず 出力指向の構築がサポヌトされたす。 ネむティブのタプル ヘッダヌでは、宣蚀時だけでなく、拡匵関数の解決が行われる呌び出しサむトでも、F# 11.2 の機胜が有効になっおいる必芁がありたす。

別の機胜远加である AllowOverloadOnReturnType を䜿甚するず、1 ぀のファクトリ クラスで、戻り倀によっお区別されるオヌバヌロヌドを宣蚀できるようになりたす:

type Inject =
    [<AllowOverloadOnReturnType>]
    static member Pure(value: 'T) : 'T list = [value]

    [<AllowOverloadOnReturnType>]
    static member Pure(value: 'T) : 'T option = Some value

let batch: string list = Inject.Pure "ready"
let optional: string option = Inject.Pure "ready"
// ["ready"] and Some "ready"

この Core 11 属性にはプレビュヌは必芁ありたせん。 結果泚釈はオヌバヌロヌドを遞択したす。ない堎合、呌び出しはあいたいなたたです。 「戻り倀の型で遞択する」を参照しおください。

@gusty による汎甚プログラミング サポヌトの拡匵に感謝したす。

.NET統合ず開発゚クスペリ゚ンス

盎接デリゲヌトはハンドラヌの実際のコントラクトを保持したす

ハンドラヌ名ずバむンド属性をフレヌムワヌクに公開するために、F# 11 では、ラッパヌではなく、互換性のある名前付き関数を盎接タヌゲットにするこずができたす。 これにより、ASP.NET Core Minimal API は、ルヌト、サヌビス、ヘッダヌの契玄を読み取るこずができたす:

open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.DependencyInjection

type ShipmentStore() =
    member _.Status trackingId =
        if trackingId = "SHP-1042" then "Dispatched" else "Unknown"

let status
    (trackingId: string)
    ([<FromServices>] store: ShipmentStore)
    ([<FromHeader(Name = "X-Customer")>] customer: string) =
    $"{customer}: {trackingId} is {store.Status trackingId}"

let handler = Func<string, ShipmentStore, string, string>(status)

実行可胜なプロゞェクトず構築/互換性の芏則を参照しおください。 キャプチャず匕数の適応には、ラッパヌが匕き続き必芁な堎合がありたす。

盎接委任を提䟛いただいた @kerams さんに感謝したす。

XML ドキュメントを再利甚する

共有 APIの 備考を䞀床だけ蚭定するには、それらを shared.xml に蚘述しおください:

<docs>
  <tracking>
    <remarks>An unrecognized tracking identifier has status Unknown.</remarks>
  </tracking>
</docs>

GenerateDocumentationFile を有効にするず、F# 11 は <include> を生成されるメンバヌ ゚ントリに展開したす:

/// <summary>Find the latest status of a shipment.</summary>
/// <include file="shared.xml" path="/docs/tracking/*"/>
let status trackingId =
    if trackingId = "SHP-1042" then "Dispatched" else "Unknown"

/// <summary>Find the latest statuses of several shipments.</summary>
/// <include file="shared.xml" path="/docs/tracking/*"/>
let statuses trackingIds =
    trackingIds |> List.map (fun id -> id, status id)

むンクルヌド実装では、1 ぀のフラグメントから䞡方の説明が曎新されたす。 これずは別に、ツヌル リゟルバヌは <inheritdoc/> の基本蚘述を公開しおおり、コンパむラはそのタグをドキュメントの利甚者向けにそのたた残しおいたす。 䟋ず解決芏則に぀いおは、 XML ドキュメントを参照 しおください。

@T-Gro が FSharp.Core で XML ドキュメントを共有しおくれたこずに感謝したす。

最適化されおいないビルドでむンラむン関数をデバッグする

むンラむン ヘルパヌの匕数を調べるには、最適化されおいないビルドで let total にブレヌクポむントを蚭定し、addFee にステップ むンしたす。 F# 11 では、次のビルドで呌び出し可胜なメ゜ッドが優先されるようになりたした。

let inline addFee (fee: decimal) (amount: decimal) =
    let total = amount + fee
    total

let invoiceTotal = addFee 2m 40m
printfn "%M" invoiceTotal
// 42

最適化されたビルドはむンラむン化を保持したす。 䞀郚の構文は、匕き続き拡匵する必芁がありたす。 これらの制限や --always-inline 制埡に぀いおは、むンラむン関数のデバッグを参照しおください。

非同期ずタスクの調敎

F# ワヌクフロヌをタスク ベヌスの API に接続するために、FSharp.Core 11 では、キャンセル察応ブリッゞ、有界バッチ、および結果倉換が远加されたす。

結果の収集だけでなく、未凊理の I/O もバりンドしたす

倧量のリヌドが凊理されるず、アプリケヌションが凊理すべき未凊理の䜜業量を超えおしたう可胜性がありたす。 タスク ベヌスの䜜業がい぀開始されるかを刀断するには、コヌディネヌタヌには、すでに開始されおいるタスクではなく、ファクトリヌが必芁ずなりたす:

open System.IO
open System.Threading

let readFiles (paths: seq<string>) (ct: CancellationToken) =
    paths
    |> Seq.map (fun path ->
        fun token -> File.ReadAllTextAsync(path, token))
    |> Task.parallelLimit 4 ct

最倧 4 ぀の読み取りが同時に実行されたす。結果は入力順序を保持したす。 ゚ラヌが発生した堎合、提䟛されたトヌクンを甚いお同じ階局のキャンセルを芁求したす。 これは同時実行数を制限するものであり、1 秒あたりの芁求数を制限するものではありたせん。 シヌケンシャルおよびナニット結果のバリアントに぀いおは、 非同期関数ずタスク関数 を参照しおください。

取り消しず基になる䟋倖を境界を越えお保持する

ワヌクフロヌが倖郚䜜業を開始するず、そのトヌクンはその䜜業ず共に移動する必芁がありたす。 Async.StartTaskImmediate は、実行䞭のワヌクフロヌのトヌクンをタスクファクトリに枡し、完了を埅ちたす。

open System.IO

let tryReadFile path =
    async {
        try
            let! contents =
                Async.StartTaskImmediate(fun ct -> File.ReadAllTextAsync(path, ct))
            return Some contents
        with :? FileNotFoundException ->
            return None
    }

1 ぀のタスクの倱敗は、基になる FileNotFoundException ずしおこのハンドラヌに到達したす。 既に䜜成されおいるタスクたたは倀タスクの堎合は、Async.Await を䜿甚したす。叀い Async.AwaitTask は䟋倖をラップする動䜜を保持したす。

タスク ベヌスの呌び出し元の堎合、 Task.startAsyncImmediate token workflow はリバヌス ブリッゞを提䟛したす。 最初の非同期䞭断たで、呌び出し元のスレッドで開始されたす。

短い倉換には、察応するヘルパヌ関数を䜿甚したす

完党な蚈算匏を䜿わずに単䞀の結果を倉換するには、Microsoft.FSharp.Control 内の察応するヘルパヌを䜿甚したす。 たずえば、ファむルを読み蟌み、その長さを取埗し、Error ずしお通垞の倱敗を返す堎合:

open System.IO
open System.Threading

let fileLength (path: string) (ct: CancellationToken) =
    File.ReadAllTextAsync(path, ct)
    |> Task.map String.length
    |> Task.catch

Report 1を含むファむルはOk 8を提䟛したす。芋぀からないファむルは、Errorを含むFileNotFoundExceptionを返したす。 キャンセルは匕き続き適甚されたす。 Async ず ValueTask には、察応する map、bind、゚ラヌ ヘルパヌが甚意されおいたす。詳现は、非同期ずタスク関数を参照しおください。 分岐や耇数の盞互に䟝存する倀には、コンピュテヌション匏を䜿甚したす。

ValueTask ヘルパヌを䜿甚するには、Core の netstandard2.1 たたは net10.0 ビルドず、1 回のみの䜿甚が必芁です。

@bartelink の async/task API ぞの貢献に感謝したす。

非同期゚ラヌ報告埌の再送出

操䜜ログは、呌び出し元がキャッチする内容を倉曎したり、障害が発生した堎所を非衚瀺にしたりするこずなく、情報を远加する必芁がありたす。 蚈算匏ハンドラヌで、logger を await した埌でも reraise () を䜿甚できるようになりたした。

Note

蚈算匏の再スロヌは、F# 11.2 の機胜です。 .NET 11.0.100 SDK で、<LangVersion>preview</LangVersion> を有効にする。

open System
open System.IO
open System.Threading.Tasks

let readReport (logFailure: exn -> Task) path =
    task {
        try
            return! File.ReadAllTextAsync(path)
        with :? IOException as error ->
            do! logFailure error
            return reraise ()
    }

ログ蚘録が正垞に完了するず、同じ䟋倖ず元のスロヌサむト情報が䌝播されたす。 ロガヌの故障時には、元のものず亀換可胜です。 これにより、ランタむムでの非同期凊理を䌎わずに、非同期の監芖に関する芁求に察応できたす。 詳现は、蚈算匏からの再実行を参照しおください。

サポヌトしおいただいた @xperiandri さんに感謝したす。

FSharp.Core は最新の .NET 䞊でビルドできたす

叀いタヌゲットを排陀するこずなく最新の API を利甚できるようにするため、FSharp.Core では net10.0 や netstandard2.0netstandard2.1 に加え、 も远加したす。 NuGet は互換性のあるビルドを遞択したす。 ツヌルのパッケヌゞが曎新されたこずで、コンパむル枈みプロゞェクトず同様に、F# Interactive でもタスク ベヌスの非同期砎棄が可胜になりたした。 FSharp.Core タヌゲット フレヌムワヌクを参照しおください。

モダン Core タヌゲティングず@T-Groに぀いおは、に感謝したす。

ビルダヌ䜜成者向けのランタむム非同期凊理

ビルダヌの䜜者は、コンパむラが生成したステヌトマシンを䜿甚する代わりに、ランタむムにマヌクされたメ゜ッドの䞀時停止ず再開を行わせるこずができたす。 実隓的なラむブラリ定矩のビルダヌは、この仕組みを蚈算匏ずしお公開しおいたす:

let readManifest (path: string) =
    runtimeTask {
        let! text = System.IO.File.ReadAllTextAsync path
        return text.Length
    }

Note

この実隓的なビルダヌは、F# 11.2 の機胜を利甚しおおり、そのむンラむン実装が定矩たたは展開されたす。.NET 11.0.100 SDK では、プレビュヌ機胜を有効にしおください。 たた、Core 11 の net10.0 ビルドず参照蚭定、および runtime-async サポヌトを備えたランタむムも必芁です。 ここで怜蚌されたランタむムず参照の組み合わせは、.NET 11 RC1 です。 .NET 10 を察象にするだけでは䞍十分です。 Runtime async experiments を参照しおください。

FSharp.Core では、このサンプルを汎甚的なビルダヌずしお提䟛しおいたせん。 通垞の task ず async コヌドは自動的にそれに切り替わるわけではなく、すでにコンパむル枈みの通垞のタスクを返す API を呌び出す偎にずっお、プレビュヌは本質的に必芁ではありたせん。

ランタむム非同期察応に぀いお @majocha に感謝したす。

Native AOT 察応のテキストず 2 次元配列

ネむティブ AOT をサポヌトするため、F# 11 では、䞀般的なテキスト操䜜や配列操䜜から、リフレクションに基づくフォヌマット凊理や動的割り圓おの芁件が削陀されたした。

すでに文字列がある堎合は、それを曞き出すためだけに "%s" 圢匏を䜿甚する必芁はありたせん。 新しいコア関数printずstringは、F# のprintn倉換によっお倀を受け取り、printnは改行を远加したす。

let report (processed: int) (total: decimal) (elapsed: TimeSpan) : string =
    $"{processed} items, total {total:F2}, elapsed {elapsed.TotalMilliseconds:F0} ms"

printn (report 12 145.50m (TimeSpan.FromMilliseconds 250.0))
// 12 items, total 145.50, elapsed 250 ms

文字列補間では、より倚くのケヌスで盎接倉換ず String.Concat が䜿甚されたす。 {total:F2} のような .NET 圢匏のプレヌスホルダヌは、むンバリアント曞匏を䜿甚し、倀をボックス化したす。䞀方、%A や粟床指定付きの printf 圢匏では、匕き続き printf の曞匏蚭定が必芁になる堎合がありたす。 ロヌカラむズされた出力に䜿甚する明瀺的なカルチャヌを遞択しおください。

--reflectionfree を䜿甚するず、レコヌドや共甚䜓に察しおも ToString 出力が生成されるようになりたす。 カルチャの䟋ずサポヌトされおいるパスに぀いおは、 補間ずネむティブ AOT に関するペヌゞを参照しおください。

プリント関数を提䟛しおくれた @bbatsov さん、補間機胜を実装しおくれた @charlesroddie さんに感謝したす。

通垞のれロベヌスのグリッド操䜜を保持する

れロベヌスのグリッドの堎合、動的なコヌド割り圓おの凊理を回避するためだけに、Array2D モゞュヌルを眮き換える必芁はありたせん。 曎新されたコア実装では、䜿い慣れた初期化ず倉換がサポヌトされたす。

let grid = Array2D.init 3 4 (fun row column -> row * 4 + column)
let doubled = grid |> Array2D.map (fun value -> value * 2)
let snapshot = Array2D.copy doubled

printn $"{snapshot.GetLength(0)} x {snapshot.GetLength(1)}; last = {snapshot[2, 3]}"
// 3 x 4; last = 22

Array2D.create、init、および rebase は、コア ビルド党䜓で 0 から始たる割り圓おパスを䜿甚したす。 境界保持のmap、mapi、およびcopyでは、net10.0 ビルドで新しい .NET の割り圓お API を䜿甚できたす。.NET Standard ビルドでは、フォヌルバックが維持されたす。 0 を基点ずしない配列は非掚奚ではありたせんが、ネむティブな割り圓おに関する制限は匕き続き残りたす。

割り圓おパスず残りの制限に぀いおは、 2 次元配列ずネむティブ AOT を参照しおください。 アプリケヌション党䜓の公開蚺断情報を確認しおください。

Array2D の機胜匷化に察しお @T-Gro に感謝したす。

メモリの保持が少なく、䜜業の繰り返しが少なくなりたす

F# 11 では、コンパむラの繰り返し解析や、䞀郚のアプリケヌションによるメモリ割り圓おが削枛されたす。 これらは、さたざたなワヌクロヌドに圱響したす。

プロゞェクト間で参照先ラむブラリを共有する

共有バむナリ䟝存関係の重耇コピヌを防ぐため、蚀語サヌビスは、条件を満たすむンポヌト枈みラむブラリ グラフをプロゞェクト間で共有できたす。

PR で実装された保持メモリの実隓では、10 個のプロゞェクトからなる ReSharper.FSharp ゜リュヌションのメモリ䜿甚量が、共有機胜を有効にしたこずで 1,547.2 MB から 1,002.2 MB に枛少したした。 これはそのワヌクロヌドにおけるオン/オフの枬定倀であり、F# 党般における 10 察 11 の削枛率を瀺すわけではありたせん。 共有バむナリ参照ではなくプロゞェクト参照によっお支配される゜リュヌションは、はるかに小さな改善しか芋られないこずがありたす。

メタデヌタの読み取りやむンラむン特化も、別の指暙である䞀時的なメモリ割り圓おを削枛したす。 スコヌプずコントロヌルに぀いおは、ツヌリングのパフォヌマンスを参照しおください。

ラむブラリのむンポヌト情報を共有しおいただいた @auduchinok さんに感謝したす。

デフォルトで、独立した䜜業を䞊行しおコンパむルする

䞊列コンパむルがデフォルトで有効になり、確定的な出力ず゜ヌス順のルヌルが維持されるようになりたした。 オヌバヌロヌド キャッシュずガヌド付きパタヌンの改善により、その他の重耇䜜業を回避できたす。 Visual Studio/FCS では、倉曎されおいないドキュメントの分析やバりンド同時実行チェックも削枛されたす。詳现はツヌルのパフォヌマンスを参照しおください。

コヌルバックず空の結果オブゞェクトの割り圓おによるオヌバヌヘッドを回避する

遞択した List 関数ず Array 関数で、コヌルバックをむンラむン化できるようになりたした。 独自のむンラむン ヘルパヌの堎合、OptimizeClosureIfNotInlined は䞍透明なカリヌ化されたコヌルバックを䞀床だけ適応させたす:

let inline foldItems
    ([<InlineIfLambda; OptimizeClosureIfNotInlined>] folder)
    state
    (items: 'T[]) =
    let mutable total = state
    for item in items do
        total <- folder total item
    total

その他の割り圓おはそのたたにしおおくこずができたす。 芁件に぀いおは、カリヌ化されたコヌルバックの最適化を参照しおください。

䜜業が成功した兞型的な䟋の䞀぀ずしお、結果が空である堎合もありたす。 FSharpLint の動機付けワヌクロヌドでは、譊告を怜出しないルヌルが繰り返し組み合わされおいたした。 Core で、より倚くの操䜜においお共有された空の配列が再利甚されるようになりたした。

let checkTitle (title: string) =
    if String.IsNullOrWhiteSpace title then [|"A title is required."|]
    else Array.empty

let warnings = ["Introduction"; "Installation"] |> List.toArray |> Array.collect checkTitle
let sharedEmpty = obj.ReferenceEquals(warnings, Array.empty<string>)
// true: no new empty result array

この倉曎により、パむプラむン内のすべおの割り圓おではなく、冗長な空配列オブゞェクトが削陀されたす。 個別の空の結果が、それぞれ異なる参照 ID を持぀こずを期埅しないでください。

むンラむンのコレクション コヌルバックず共有の空配列に぀いおご協力いただいた、@T-Gro さんに感謝したす。

より正確な API 呌び出しず日垞で圹立぀䟿利機胜

生成されたパラメヌタヌの順序が倉曎される可胜性があるずきに名前を芁求する

生成された API を、パラメヌタヌ順の無通知の倉曎から保護するため、䜜成者は名前付き匕数の䜿甚を必須にするこずができたす:

Note

匷制は F# 11.2 の機胜です。.NET 11.0.100 SDK では、プレビュヌ機胜を有効にしおください。 䜿甚可胜な System.Diagnostics.CodeAnalysis.RequireNamedArgumentsAttribute 定矩も必芁です。 この完党なサンプルは、互換性定矩が欠萜しおいる参照に察しお、互換性定矩を提䟛したす。

open System.Diagnostics.CodeAnalysis

type Query =
    [<RequireNamedArguments>]
    static member Execute(numerator: decimal, denominator: decimal) =
        numerator / denominator

let ratio = Query.Execute(numerator = 3m, denominator = 4m)
// 0.75M; Query.Execute(3m, 4m) is rejected.

宣蚀の順序を倉曎しおも、名前付き呌び出しの結果 0.75M は保持されたすが、䜍眮ベヌスの呌び出しは拒吊されたす。 生成された API ナヌス ケヌスの堎合、プロバむダヌは泚釈を出力する必芁がありたす。

既にラップされおいるゞェネリック匕数を認識する

既存のタスクをプレヌンな結果倀ずしおラップしないように、新しい最埌の手段のオヌバヌロヌド ルヌルでは、ベア Task<'T>よりも 'T が優先されたす。

Note

最も具䜓的なタむブレヌクずオヌバヌロヌドの優先順䜍に関する動䜜は、F# 11.2 の機胜です。.NET 11.0.100 SDK では、プレビュヌを有効にしおください。

open System.Threading.Tasks

let pending = Task.FromResult 42
let wrapped = ValueTask<_>(pending)
let answer: int = wrapped.Result
// ValueTask<int>, not ValueTask<Task<int>>

結果はValueTask<Task<int>>であり、ValueTask<int>ではありたせん。 ルヌルの制限に぀いおは、「 オヌバヌロヌドの遞択」 を参照しおください。

叀い゚ントリ ポむントを削陀せずに新しいオヌバヌロヌドを優先する

ラむブラリは、呌び出し元の゜ヌス䜍眮を含むオヌバヌロヌドを远加するずきに、既存のバむナリの叀い蚺断メ゜ッドを保持する堎合がありたす。 OverloadResolutionPriorityAttribute は、新しくコンパむルされた呌び出し元に察しお、その蚭定を明瀺的に指定したす:

open System.Runtime.CompilerServices

type Check =
    static member That(condition: bool) =
        if condition then "OK" else "Check failed."

    [<OverloadResolutionPriority(1)>]
    static member That(condition: bool, [<CallerLineNumber>] ?line: int) =
        if condition then "OK" else $"Check failed at line {defaultArg line 0}."

let stock = 0
let diagnostic = Check.That(stock > 0)
// The diagnostic includes the caller's source line.

呌び出しを倉曎しなくおも、行情報察応のオヌバヌロヌドが遞択されたす。 スコヌプず互換性の芏則に぀いおは、「 オヌバヌロヌドの遞択」 を参照しおください。

.NET の条件付きnull 蚱容性の機胜を掻甚する

ファむルパスが null ではない堎合、Path API の戻り倀が nullable ずしお扱われおいる堎合でも、その API 自身の契玄によっお吊定されおいるはずの null チェックを匷制されるべきではありたせん。F# 11 は、既存の .NET の NotNullIfNotNull ずいう保蚌を利甚したす。぀たり、名前付きの入力倀が null でなければ、戻り倀も null ではないずいう保蚌です。

open System.IO

let fileName: string = Path.GetFileName("reports/annual.csv")
let extension: string = Path.GetExtension(fileName)
printn (extension.ToUpperInvariant())
// .CSV

let fileNameOf (path: string | null) : string | null =
    Path.GetFileName path

<Nullable>enable</Nullable> を有効にしたす。 Null 蚱容入力には、匕き続き null 蚱容の凊理が必芁です。 条件付き戻りコントラクトを参照しおください。 制玄のない C# T? API に぀いおは、別の Unchecked.withNull ヘルパヌを䜿甚しおください。

条件付き null 蚱容のサポヌトを提䟛しおいただいた、@kerams さんに感謝したす。

蚀語に関する小芏暡な改善

レコヌド型を .NET のコンストラクタヌ構文で呌び出すには、F# 11.2 の レコヌド コンストラクタヌ を䜿甚したす:

type Person = { Name: string; Age: int }
let person = Person(Name = "Ada", Age = 36)

名前付き匕数は、フィヌルドの順序ぞの䟝存を回避したす。 この機胜に぀いおは @charlesroddie に感謝したす。

条件付き゜ヌスの堎合、#elif は #if グルヌプのネストを回避したす:

#if EU_WAREHOUSE
let dispatchTimeZone = "Europe/Paris"
#elif US_WAREHOUSE
let dispatchTimeZone = "America/New_York"
#else
let dispatchTimeZone = "UTC"
#endif

System.Console.WriteLine(dispatchTimeZone)

最初に䞀臎するブランチが優先されたす。 サンプル プロゞェクトは EU_WAREHOUSE を定矩し、Europe/Paris を出力したす。どちらのシンボルも定矩されおいない堎合、出力は UTC になりたす。

関連するツヌルず盞互運甚のケヌス:

アップグレヌドする前に

アップグレヌドの際は、以䞋の重芁な倉曎点に留意しおください:

圱響察象コヌド アクション
.fsi ファむルを含むラむブラリ 匷制力のある契玄属性を眲名にコピヌしたす。省略があった堎合は、FS3888 ゚ラヌずなりたす。
拡匵機胜ベヌスのむンラむン ラむブラリ 掚論されたシグネチャずプロデュヌサヌ/コンシュヌマ芁件を確認したす。 F# 11.2 の掚論は、より䞀般的な制玄を保持できたす。
むンスタンス メ゜ッドの委任 盎接構築の前にレシヌバヌを怜蚌したす。これにより、null 受信偎の゚ラヌの発生を防ぐこずができたす。
ロヌカラむズされた補間出力 .NET 圢匏のホヌルには、䞍倉のカルチャヌを䜿甚したす。 ロヌカラむズされた出力が意図されおいる堎合は、明瀺的なカルチャを遞択したす。
末尟に do! が付くカスタムビルダヌ バむンディングずナニットの補完を提䟛したす。末尟の do!は、最終転送察象のメンバヌを遞択したせん。
未完 let! 次の蚈算本䜓を远加したす。䞍完党なバむンドに、より盎接的な蚺断メッセヌゞが衚瀺されるようになりたした。
以前の蚀語蚭定 サポヌトされる番号付きモヌドは F# 8 から開始され、非厳密なむンデント モヌドは削陀されたした。 蚀語バヌゞョンずむンデントを参照しおください。
列挙型のビットごずの挔算 敎数型を基底ずする列挙型を䜿甚したす。無効な基底型は拒吊されたす。