Files
affaan-m--everything-claude…/docs/ja-JP/rules/fsharp/coding-style.md
T
wehub-resource-sync d48cda4081
CI / Test (ubuntu-latest, Node 18.x, bun) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, npm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, pnpm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, yarn) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 20.x, bun) (push) Failing after 17m13s
CI / Test (ubuntu-latest, Node 20.x, npm) (push) Failing after 18m42s
CI / Test (ubuntu-latest, Node 20.x, pnpm) (push) Failing after 15m0s
CI / Test (ubuntu-latest, Node 20.x, yarn) (push) Failing after 49m44s
CI / Test (ubuntu-latest, Node 22.x, bun) (push) Failing after 51m55s
CI / Test (ubuntu-latest, Node 22.x, pnpm) (push) Failing after 21m57s
CI / Test (ubuntu-latest, Node 22.x, npm) (push) Failing after 37m39s
CI / Test (ubuntu-latest, Node 22.x, yarn) (push) Failing after 34m7s
CI / Validate Components (push) Failing after 37m15s
CI / Python Tests (push) Failing after 10m1s
CI / Security Scan (push) Failing after 10m1s
CI / Lint (push) Failing after 17m12s
CI / Coverage (push) Failing after 20m19s
CI / Test (macos-latest, Node 18.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, yarn) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:55:55 +08:00

3.5 KiB

paths
paths
**/*.fs
**/*.fsx

F# コーディングスタイル

このファイルは common/coding-style.md を F# 固有のコンテンツで拡張します。

標準

  • 標準的な F# の規約に従い、正確性のために型システムを活用する
  • デフォルトでイミュータビリティを優先する。パフォーマンス上の理由がある場合のみ mutable を使用する
  • モジュールを焦点を絞り、凝集性を保つ

型とモデル

  • ドメインモデリングにはクラス階層よりも判別共用体を優先する
  • 名前付きフィールドを持つデータにはレコードを使用する
  • プリミティブ型に対する型安全なラッパーには単一ケース共用体を使用する
  • 相互運用またはミュータブルなステートが必要でない限り、クラスの使用を避ける
type EmailAddress = EmailAddress of string

type OrderStatus =
    | Pending
    | Confirmed of confirmedAt: DateTimeOffset
    | Shipped of trackingNumber: string
    | Cancelled of reason: string

type Order =
    { Id: Guid
      CustomerId: string
      Status: OrderStatus
      Items: OrderItem list }

イミュータビリティ

  • レコードはデフォルトでイミュータブル。更新には with 式を使用する
  • ミュータブルなコレクションよりも listmapset を優先する
  • ドメインロジックで ref セルとミュータブルフィールドを避ける
let rename (profile: UserProfile) newName =
    { profile with Name = newName }

関数スタイル

  • 大きなメソッドよりも小さく合成可能な関数を優先する
  • パイプ演算子 |> を使用して読みやすいデータパイプラインを構築する
  • if/else チェーンよりもパターンマッチングを優先する
  • null の代わりに Option を使用する。失敗する可能性のある操作には Result を使用する
let processOrder order =
    order
    |> validateItems
    |> Result.bind calculateTotal
    |> Result.map applyDiscount
    |> Result.mapError OrderError

非同期とエラーハンドリング

  • .NET の非同期 API との相互運用には task { } を使用する
  • F# ネイティブの非同期ワークフローには async { } を使用する
  • パブリック非同期 API を通じて CancellationToken を伝播する
  • 予期されるエラーには例外ではなく Result とRailway指向プログラミングを優先する
let loadOrderAsync (orderId: Guid) (ct: CancellationToken) =
    task {
        let! order = repository.FindAsync(orderId, ct)
        return
            order
            |> Option.defaultWith (fun () ->
                failwith $"Order {orderId} was not found.")
    }

フォーマット

  • 自動フォーマットには fantomas を使用する
  • 意味のある空白を優先する。不要な括弧を避ける
  • 未使用の open 宣言を削除する

open 宣言の順序

open 文を4つのセクションに空行で区切ってグループ化し、各セクション内は辞書順で並べる:

  1. System.*
  2. Microsoft.*
  3. サードパーティの名前空間
  4. ファーストパーティ / プロジェクトの名前空間
open System
open System.Collections.Generic
open System.Threading.Tasks

open Microsoft.AspNetCore.Http
open Microsoft.Extensions.Logging

open FsCheck.Xunit
open Swensen.Unquote

open MyApp.Domain
open MyApp.Infrastructure