Skip to content
Published on

モダン F# 2026 — F# 9 (.NET 9) / Saturn / Giraffe / Bolero / Fable / Feliz / Elmish / Fantomas 徹底ガイド

Authors

プロローグ — 2026 年でも F# を書く人たちはいる

毎年、誰かが聞く。「F#? まだ使ってる人いるの?」

いる。それも .NET の世界の中でますます真剣に。

  • Jet.com(現 Walmart Labs の一部)は 2010 年代半ばからプライシングエンジンを F# で書いた。買収後もコアのプライシングモデルの一部は F# のまま残った。
  • Microsoft 自身、コンパイラチームと Azure の一部サービス(コスト計算、ライセンス、分析)が F# を出荷している。F# 自体、Microsoft Research Cambridge の Don Syme が 2005 年から作っている言語だ。
  • CitiBank, Credit Suisse, Standard Chartered, Bank of America — 金融ドメインのプライシング・リスクモデルでは、F# は安定して一席を占めている。ドメインモデリングが強く、副作用を型で囲い込むのに向いている。
  • AT&T, Demetrix, Indaba Music, GameSys, Tachyus, G-Research — データパイプライン、ML、ゲームバックエンドで F# コードが動いている。
  • 日本では ユーザックシステム (Usac System) が、東京・大阪・名古屋で自動化と物流の自社プロダクトを F# と .NET で作っている。Microsoft Japan の F# エバンジェリストがよく言及する。

2010 年代の F# の敵は「書きづらい」ではなかった。本当の敵は 「Mono 時代は非 Windows でビルドが壊れ、Visual Studio for Mac は半分しか動かず、Paket か NuGet かを決められない」 だった。それが 2026 年にはどうなったか。

答え: .NET 9 は本気でクロスプラットフォームになり、F# 9 は nullable reference types を完成させ、Fantomas は標準フォーマッタとして定着した。だから「自分のノート PC では動かない」という事故はほぼ消えた。dotnet CLI 1 本で Windows・macOS・Linux で同じように動く。

この記事は 2026 年の F# スタックを一息で見渡す。コンパイラ、Web フレームワーク、クライアントサイド、デスクトップ UI、ビルドツール、データ、数値・ML、SQL、パーサ、そして人々まで。


1. 2026 年のモダン F# — .NET 9 の時代

まず 1 枚の風景を。

                  モダン F# 2026 スタック

[ランタイム]       .NET 9 (2024.11, LTS) — 単一クロスプラットフォーム SDK
[コンパイラ]       F# 9 (2024.11) / F# 10 preview (GitHub main)
[ビルド]           dotnet CLI / FAKE / Paket / MSBuild

[Web バックエンド] Saturn (Rails スタイル, opinionated)
                   Giraffe (関数型 ASP.NET Core ミドルウェア)
                   Suave (旧式, 自前 HTTP)

[Web クライアント] Fable (F# to JS) + Feliz (React) + Elmish (Elm pattern)
                   Bolero (Blazor WebAssembly + F#)

[デスクトップ]     Avalonia.FuncUI (宣言的クロスプラットフォーム UI)

[ツール]           Fantomas (フォーマッタ) / Ionide (VS Code) / FsAutoComplete
                   Polyglot Notebooks (Jupyter on .NET)

[データ]           FSharp.Data (CSV/JSON/XML/SQL type provider)
                   Donald (薄い SQL クライアント)

[数値・ML]         MathNet.Numerics (線形代数)
                   DiffSharp (自動微分, PyTorch スタイル)
                   TorchSharp (libtorch バインディング) + ML.NET

[並行性]           Hopac (Concurrent ML スタイル)
                   async / Task

[パーサ]           FParsec (Parsec の移植)

[クラウド]         F# in Azure Functions / AWS Lambda
                   F# in Aspire (.NET 分散ワークフロー)

[本番ユーザー]     Jet.com (Walmart) / Microsoft / CitiBank /
                   Credit Suisse / GameSys / Tachyus / Usac

これが 2026 年の F# の地形図だ。1 つずつ箱に入っていこう。


2. F# 9 (2024.11, .NET 9 同時) — nullable と DU の改善

F# 9 は 2024 年 11 月、.NET 9 と同時に正式リリースされた。.NET 9 は 12 ヶ月 STS リリースだが、F# 9 自体は SDK にバンドルされ、次の .NET 10 LTS(2025 年 11 月予定)に自然に乗っていく。

中心の変更は 3 つ。

Nullable reference types の完成

C# は 2019 年の C# 8 で ? による nullable reference types を導入した。F# はそもそも Option('T option)を持っていたので、長らく「F# コードは null をほぼ見ない」というスタンスだった。だが BCL(C# で書かれた .NET の標準ライブラリ)との相互運用のたびに null が漏れてきた。

F# 9 は 相互運用の境界で nullable reference types を一級市民にする

// F# 9: nullable annotation
let processName (name: string | null) =
    match name with
    | null -> "(anonymous)"
    | n -> n.ToUpper()

// C# のメソッドを呼ぶときも安全
let s: string | null = System.Environment.GetEnvironmentVariable("HOME")
match s with
| null -> printfn "HOME not set"
| home -> printfn "HOME = %s" home

string | null は C# 9 の string? に正確に対応する。コンパイラはこれをチェックし、「null を unwrap せずにメソッド呼び出ししたら警告」を出す。

Discriminated union の改善

DU(discriminated union)は F# の魂だ。F# 9 は 2 つを改善した。

  1. struct DU のボクシングコスト削減[<Struct>] の DU をより積極的にスタックに留める。
  2. union case 単位の可視性private/internal を union の各 case にも適用できる。
[<Struct>]
type Result<'T, 'E> =
    | Ok of value: 'T
    | Error of error: 'E

// case 単位の可視性
type DbHandle =
    private | Open of System.Data.IDbConnection
            | Closed

標準ライブラリの改善

  • List.randomShuffle, Array.randomChoice などのランダム性ヘルパー。
  • Result モジュールの拡張: Result.toList, Result.toOption, Result.toArray
  • Seq.tryExactlyOne — ちょうど 1 要素のときだけ Some、それ以外は None。
let xs = [1; 2; 3]
let shuffled = xs |> List.randomShuffle
// 例: [2; 1; 3]

let oneOnly = [42] |> Seq.tryExactlyOne
// Some 42

let twoElems = [1; 2] |> Seq.tryExactlyOne
// None

3. F# 10 プレビュー — GitHub で進行中

F# 10 は dotnet/fsharp のメインブランチで活発に開発されている。2026 年 5 月時点で、次の候補機能が RFC(Request for Comments)に上がっている。

tasklet! 短縮形

task { ... } 内で複数の非同期結果を合流させるとき、let! を並べると長くなる。F# 10 はそれを短く書ける式ビルダ拡張を検討中。

// F# 9 スタイル
task {
    let! a = getUserAsync userId
    let! b = getOrdersAsync userId
    return (a, b)
}

// F# 10 プレビューで検討中のショート形式
task {
    let! (a, b) = getUserAsync userId, getOrdersAsync userId
    return (a, b)
}

Type provider の非同期化

FSharp.DataJsonProvider, CsvProvider はコンパイル時にスキーマを取りに行ってから型を作る。大きなスキーマでは IDE が固まる問題があった。F# 10 は type provider 呼び出しを非同期にする基盤を入れようとしている。

Resumable code の改善

F# 6 で導入された resumable code(task { }, taskSeq { } の基盤)はコンパイラ内部の機能だが、F# 10 はそれをユーザーにより安全に公開しようとしている。Hopac や独自の effect ライブラリを作るときに役立つ。

Self-type 制約

C# 11 の static abstract インターフェイスメンバに対応する F# 側の文法。SRTP(Statically Resolved Type Parameters)をより自然に書ける。

F# 10 は .NET 10 LTS と同時に 2025 年 11 月リリース予定。


4. Saturn — Giraffe ベースの opinionated Web フレームワーク

Saturn は Krzysztof Cieslak(SAFE Stack のメンテナ、Ionide の作者)が作ったフルスタック Web フレームワーク。Giraffe の上に乗った Rails 風のレイヤー と思えばいい。

コアコンセプト

Saturn は application builder DSL を提供する。ASP.NET Core のミドルウェアパイプラインを F# のビルダ構文に折りたたんだもの。

open Saturn

let app =
    application {
        use_router topRouter
        url "http://0.0.0.0:8085/"
        use_gzip
        use_static "public"
        use_developer_exceptions
    }

run app

これが入口の全部。application { } の中の各トークンは実は関数で、Saturn が application という computation expression を定義し、use_router, url, ... の各キーワードが ApplicationBuilder に作用する。

Controller — MVC スタイル

Saturn は controller の builder も持つ。

let userController = controller {
    index (fun ctx -> "Listing all users" |> Controller.text ctx)
    show (fun ctx id -> sprintf "Showing user %i" id |> Controller.text ctx)
    create (fun ctx -> "Creating new user" |> Controller.text ctx)
    edit (fun ctx id -> sprintf "Editing user %i" id |> Controller.text ctx)
    delete (fun ctx id -> sprintf "Deleting user %i" id |> Controller.text ctx)
}

let topRouter = router {
    forward "/users" userController
}

REST 7 アクションが 1 つの builder に収まる。Rails ユーザーには馴染みの形だ。

SAFE Stack

Saturn は単独でも使えるが、たいてい SAFE Stack の一部として使われる。

  • S — Saturn (サーバー)
  • A — Azure (ホスティング)
  • F — Fable (クライアント, F# to JS)
  • E — Elmish (Elm パターン)

dotnet new SAFE でフルスタック F# プロジェクトの雛形ができる。クライアントとサーバーが同じ F# ドメイン型を共有できるのが最大の魅力。


5. Giraffe — 関数型 ASP.NET Core

Giraffe は Saturn の下半分。ASP.NET Core の HttpContext パイプラインを関数型でラップしたライブラリだ。

HttpHandler

Giraffe のコア抽象は HttpHandler

type HttpHandler = HttpFunc -> HttpContext -> HttpFuncResult
// where HttpFunc = HttpContext -> HttpFuncResult
//       HttpFuncResult = Task<HttpContext option>

「次のハンドラ」と「現在のコンテキスト」を受け取り、「更新されたコンテキスト(または None)」を Task で返す関数。これが ASP.NET Core ミドルウェアの 1 段と正確に対応する。

合成

>=> 演算子でハンドラを合成する。

open Giraffe

let webApp =
    choose [
        route "/"           >=> text "Hello, world"
        route "/json"       >=> json {| message = "hello" |}
        route "/api/users"  >=> requireAuth >=> getUsers
        routef "/user/%i"   (fun id -> sprintf "User %i" id |> text)
        setStatusCode 404   >=> text "Not Found"
    ]

choose は最初にマッチするハンドラを実行する。>=> は「このハンドラを通したあと次に続けろ」という意味。関数合成と同じ見た目だが、実体は Task<HttpContext option> を扱う Kleisli composition だ。

View — GiraffeViewEngine

HTML を F# コードで作れる。

open Giraffe.ViewEngine

let layout (content: XmlNode list) =
    html [] [
        head [] [
            title [] [ str "Giraffe" ]
            link [ _rel "stylesheet"; _href "/style.css" ]
        ]
        body [] content
    ]

let indexView =
    layout [
        h1 [] [ str "Hello, Giraffe" ]
        p [] [ str "Functional ASP.NET Core" ]
    ]

JSX に似ているが、F# の関数とリストで表現され、完全に型付けされている。


6. Bolero — Blazor + F#

Bolero は IntelliFactory で始まり、いまは fsbolero 組織がメンテしているプロジェクトで、Blazor WebAssembly の上で F# で SPA を作れるようにしてくれる

なぜ Bolero か

  • Blazor は C# で WebAssembly SPA を作る Microsoft の公式フレームワーク。
  • Bolero はその上に F# と Elmish(MVU)パターンを乗せる。
  • 結果: 型安全 + コンポーネント + F# DSL の HTML + Elm 風の状態管理
open Bolero
open Bolero.Html
open Elmish

type Model = { count: int }

type Message =
    | Increment
    | Decrement

let init () = { count = 0 }, Cmd.none

let update msg model =
    match msg with
    | Increment -> { model with count = model.count + 1 }, Cmd.none
    | Decrement -> { model with count = model.count - 1 }, Cmd.none

let view model dispatch =
    div {
        h1 { "Bolero Counter" }
        p { sprintf "Count: %d" model.count }
        button {
            on.click (fun _ -> dispatch Increment)
            "+"
        }
        button {
            on.click (fun _ -> dispatch Decrement)
            "-"
        }
    }

Bolero の div { }, button { } は computation expression。子要素・属性・イベントハンドラを自由に混在できる。

Server-side と WebAssembly

Bolero は 2 つのホスティングモデルをどちらもサポートする。

  • Server-side Blazor — UI 更新は SignalR を介してサーバーで起きる。
  • Blazor WebAssembly — F# コードが .NET IL にコンパイルされ、WASM ランタイムで直接動く。

WebAssembly モードはサーバー負荷がないが初期ダウンロードが大きめ。Bolero 3.x から AOT(Ahead-Of-Time)コンパイルをサポートし、起動が大幅に速くなった。


7. Fable — F# to JavaScript

Fable は Alfonso Garcia-Caro が始めた F# to JavaScript コンパイラ。いまは Maxime Mangel をはじめとするコアチームがメンテしている。

Fable 5

2024 年に出た Fable 5 は複数のバックエンドをサポートする。

  • JavaScript — デフォルト。Node.js、ブラウザで動く。
  • TypeScript.ts ファイルとして出力。既存の TS コードと自然に混ざる。
  • Python — F# を Python に変換。Jupyter ノートブック、Python バックエンド。
  • Rust — 実験的。F# の安全性の一部を Rust に移す。
  • Dart — Flutter アプリを F# で書ける。
// F# ソース
module App

open Browser

let main () =
    let body = document.body
    body.innerHTML <- "<h1>Hello from F#</h1>"

main ()

これを dotnet fable でコンパイルすると JavaScript ESM が出る。

仕組み

Fable は FSharp.Compiler.Service を使って F# ソースを AST にパースし、その AST を JavaScript(または他のターゲット)に変換する。BCL 関数は Fable 自身の JS 実装(Map, Seq, List, Option, ...)にマップされる。

Fable.React / Feliz / Elmish と組み合わせて

Fable 自身はコンパイラだけ。UI ライブラリは別途入れる。

dotnet new -i Fable.Template
dotnet new fable-react
npm install
npm run start

デフォルトの Fable React テンプレートが出発点。


8. Feliz — F# React 風 DSL

Feliz は Zaid Ajaj が作った React DSL。Fable.React より短く、きれいに React コンポーネントを表現できる。

open Feliz

let helloWorld = Html.div [
    prop.className "container"
    prop.children [
        Html.h1 "Hello, Feliz"
        Html.p "F# React without JSX"
    ]
]

[<ReactComponent>]
let Counter () =
    let count, setCount = React.useState 0
    Html.div [
        Html.h2 (sprintf "Count: %d" count)
        Html.button [
            prop.onClick (fun _ -> setCount (count + 1))
            prop.text "+"
        ]
    ]
  • Html.div [ ... ] — div タグ。
  • prop.className, prop.onClick, prop.children — すべての prop が強い型を持つ。
  • [<ReactComponent>] — Feliz のコンパイラプラグインが React コンポーネントに変換。
  • React.useState, React.useEffect などすべての hook が F# シグネチャで露出。

JSX を一切書かずに React のすべてを使える。

Feliz.Bulma / Feliz.MaterialUI

エコシステムは厚い。

  • Feliz.Bulma — Bulma CSS フレームワークのラッパー。
  • Feliz.MaterialUI — Material-UI コンポーネントの F# バインディング。
  • Feliz.Recharts — Recharts チャートライブラリ。
  • Feliz.Plotly — Plotly。

主要な React ライブラリにはたいてい Feliz ラッパーがある。


9. Elmish — F# の中の Elm パターン

Elmish は Elm 言語の MVU(Model-View-Update)パターンを F# に移したライブラリ。Bolero、Fable + React、SAFE Stack の状態管理の標準だ。

3 つの関数

// 1. 初期状態
let init () : Model * Cmd<Msg> = ...

// 2. メッセージ処理
let update (msg: Msg) (model: Model) : Model * Cmd<Msg> = ...

// 3. レンダリング
let view (model: Model) (dispatch: Msg -> unit) : ReactElement = ...

それで全部。Redux や Vuex よりずっとシンプル。Elm を知っていればそのまま書き写せる。

open Elmish
open Elmish.React
open Feliz

type Model = { Count: int }

type Msg =
    | Increment
    | Decrement
    | Reset

let init () = { Count = 0 }, Cmd.none

let update msg model =
    match msg with
    | Increment -> { model with Count = model.Count + 1 }, Cmd.none
    | Decrement -> { model with Count = model.Count - 1 }, Cmd.none
    | Reset     -> { Count = 0 }, Cmd.none

let view model dispatch =
    Html.div [
        Html.h1 (sprintf "Count: %d" model.Count)
        Html.button [
            prop.onClick (fun _ -> dispatch Increment)
            prop.text "+"
        ]
        Html.button [
            prop.onClick (fun _ -> dispatch Decrement)
            prop.text "-"
        ]
        Html.button [
            prop.onClick (fun _ -> dispatch Reset)
            prop.text "Reset"
        ]
    ]

Program.mkProgram init update view
|> Program.withReactSynchronous "elmish-app"
|> Program.run

ブラウザに乗せるコードは最後の 4 行だけ。Program.mkProgram が init/update/view を受け取り、実行ループを作る。

Cmd — 副作用の隔離

Cmd<Msg> は「いま起こすべき副作用」を表す型。HTTP リクエスト、タイマー、localStorage アクセスはすべて Cmd として表現される。

let loadUserCmd userId =
    Cmd.OfPromise.either
        (fun () -> Fetch.fetchAs<User> (sprintf "/api/users/%d" userId))
        ()
        UserLoaded
        LoadFailed

update 関数は純粋なまま。副作用は Cmd で逃がしてランタイムが実行する。テストが極めて簡単。


10. Avalonia.FuncUI — 宣言的デスクトップ UI

Avalonia は WPF の精神を引き継ぐクロスプラットフォーム .NET UI フレームワーク。Windows・macOS・Linux・iOS・Android・WebAssembly で同じコードが動く。

Avalonia.FuncUI はその Avalonia の上に F# computation expression ベースの関数型 DSL を被せたもの。

open Avalonia.FuncUI.DSL
open Avalonia.Controls
open Avalonia.Layout

let view () =
    Component (fun ctx ->
        let count = ctx.useState 0

        DockPanel.create [
            DockPanel.children [
                TextBlock.create [
                    TextBlock.text (sprintf "Count: %d" count.Current)
                    TextBlock.horizontalAlignment HorizontalAlignment.Center
                ]
                Button.create [
                    Button.content "+"
                    Button.onClick (fun _ -> count.Set (count.Current + 1))
                ]
                Button.create [
                    Button.content "-"
                    Button.onClick (fun _ -> count.Set (count.Current - 1))
                ]
            ]
        ]
    )

XAML は不要。すべての UI が F# のコード。React の hook 風の useState パターンが組み込まれている。

誰が使うか

  • JetBrains Rider の一部の UI は Avalonia で作られている(IntelliJ プラットフォーム自体は Java/Kotlin だが、別ツールは Avalonia)。
  • Sirius A(F# コミュニティの IRC/Matrix クライアント)。
  • 社内ツールを F# で書きたい .NET チーム。Visual Studio for Mac 終了後、macOS で .NET UI を書ける現実的にほぼ唯一の選択肢になっている。

11. ツール — Fantomas / Paket / FAKE / Polyglot Notebooks

Fantomas

Fantomas は F# 公式フォーマッタ。Florian Verdonck らコアチームがメンテしている。

dotnet tool install -g fantomas
fantomas src/
  • コンパイラ自身の AST を使ってフォーマットするので、意味的に同等であることが保証される。
  • .editorconfig または fantomas-config.fsharpsettings でスタイルを調整。
  • VS Code(Ionide), Rider, Visual Studio に統合。

2024 年から Fantomas は F# コンパイラと同じ fsprojects/fantomas リポジトリで管理され、F# コードコンベンションの事実上の標準となっている。

Paket

Paket は NuGet の代替パッケージマネージャ。Steffen Forkmann が作った。

利点:

  • 推移的依存関係を 1 つの paket.lock ファイルに明示的に固定する(SDK 形式の PackageReference はだいぶ良くなったが、ロックの扱いはまだ微妙)。
  • GitHub リポジトリ、gist、HTTP URL を直接依存関係に追加できる。
  • F# プロジェクトで特に人気。
source https://api.nuget.org/v3/index.json

nuget Giraffe ~> 6.0
nuget FSharp.Data ~> 6.0
github fsharp/FSharp.Core

NuGet が十分良くなって Paket の存在感は縮んだが、大きなモノレポでは今でも好まれる。

FAKE

FAKE(F# Make)は F# でビルドスクリプトを書くツール。

#r "paket: nuget Fake.Core.Target //"
#load ".fake/build.fsx/intellisense.fsx"

open Fake.Core
open Fake.IO

Target.create "Clean" (fun _ -> Shell.cleanDirs [ "bin"; "obj" ])

Target.create "Build" (fun _ ->
    DotNet.build id "src/MyApp.fsproj"
)

Target.create "Test" (fun _ ->
    DotNet.test id "tests/MyApp.Tests.fsproj"
)

"Clean" ==> "Build" ==> "Test"
Target.runOrDefault "Test"

==> 演算子が依存グラフを作る。Make, Rake, Gulp の F# 版と思えばいい。

2026 年では dotnet CLI と GitHub Actions の組合せで FAKE なしでもビルドパイプラインが書けるので新規プロジェクトでは減ったが、既存コードベースでは依然として標準。

Polyglot Notebooks

Polyglot Notebooks は Microsoft のノートブック環境。Jupyter と同じ UX だが .NET 上で動き、1 つのノートブックの中に F#, C#, PowerShell, JavaScript, SQL, KQL のセルを混在できる

VS Code 拡張 Polyglot Notebooks を入れるだけ。

// F# セル
open Microsoft.DotNet.Interactive

#r "nuget: FSharp.Data, 6.4.0"

open FSharp.Data
let stocks = CsvProvider<"https://example.com/stocks.csv">.GetSample()

stocks.Rows |> Seq.take 5 |> Seq.iter (fun r -> printfn "%A" r)

データ分析・教育・レポート作成で F# が Python の代替になりうる、ほぼ唯一の現実的な道。


12. FSharp.Data — Type Provider

Type provider は F# のキラー機能。コンパイル時に外部データソースのスキーマを取得し、IDE 補完つきの強い型として公開する

CsvProvider

open FSharp.Data

type Stocks = CsvProvider<"https://example.com/stocks.csv">

let stocks = Stocks.GetSample()

for row in stocks.Rows do
    printfn "%s: open=%f, close=%f" row.Date row.Open row.Close

row.Date, row.Open, row.Close はコンパイラが CSV のヘッダーを読んで作った強い型のプロパティ。列名が変わるとコンパイルエラーで即座に分かる。

JsonProvider

type GitHubRepo = JsonProvider<"https://api.github.com/repos/dotnet/fsharp">

let repo = GitHubRepo.GetSample()

printfn "Name: %s" repo.Name
printfn "Stars: %d" repo.StargazersCount
printfn "Default branch: %s" repo.DefaultBranch

JSON レスポンスが型に自動マップされる。キー名が変わるとコンパイラが捕まえる。

SqlProvider / WorldBankProvider / FreebaseProvider

  • SqlProvider — PostgreSQL, SQL Server, SQLite, MySQL に接続してテーブル・ビュー・ストアド プロシージャを型として公開。
  • WorldBankProvider — World Bank 統計データに強い型でアクセス。
  • FreebaseProvider — Freebase は終了したが、type provider のデモとして有名だった。

Type provider は F# にしかない機能 だ。C#, Java, Kotlin にはこの種のメタプログラミングの面がない。データ処理プロジェクトなら、これ 1 つで F# を選ぶ価値がある。


13. MathNet.Numerics / DiffSharp — 数値 / 自動微分

MathNet.Numerics

MathNet.Numerics は .NET 用の数値計算ライブラリ。NumPy, SciPy の .NET 版と思えばいい。

open MathNet.Numerics.LinearAlgebra

let m = matrix [[ 1.0; 2.0 ]
                [ 3.0; 4.0 ]]

let v = vector [ 5.0; 6.0 ]

let result = m * v
printfn "%A" result
// DenseVector 2-Double
//   17
//   39

let inv = m.Inverse()
printfn "%A" inv
  • Dense / Sparse 行列。
  • BLAS / LAPACK 加速オプション(Intel MKL, OpenBLAS)。
  • 統計、積分、最適化、FFT、分布。

DiffSharp

DiffSharp は .NET 用の自動微分ライブラリ。Atılım Güneş Baydin らが作った。PyTorch のようにテンソル演算を定義すると、その微分を自動で計算してくれる

open DiffSharp

let f (x: Tensor) = x ** 2.0 + 2.0 * x + 1.0

let x = dsharp.tensor [ 1.0; 2.0; 3.0 ]
let y = f x
let dy = dsharp.diff f x

printfn "y = %A" y    // [4; 9; 16]
printfn "dy = %A" dy  // [4; 6; 8]   (つまり 2x + 2)

DiffSharp はバックエンドとして TorchSharp(libtorch C++ バインディング)や独自の reference backend を使える。GPU 加速もサポート。

研究コード、微分可能プログラミング、勾配ベースの最適化で使われる。


14. TorchSharp + ML.NET — 機械学習

TorchSharp

TorchSharp は .NET 用の PyTorch バインディング。libtorch C++ ライブラリを P/Invoke で呼ぶ。PyTorch とほぼ 1:1 対応する API を F# から使える

open TorchSharp
open type torch

let device = if cuda.is_available() then CUDA else CPU

let model =
    Sequential(
        ("fc1", Linear(784L, 256L)),
        ("relu1", ReLU()),
        ("fc2", Linear(256L, 10L))
    )
    |> fun m -> m.``to``(device)

let x = randn([| 64L; 784L |]).``to``(device)
let y = model.forward(x)
printfn "Output shape: %A" y.shape

型安全なテンソル演算、GPU サポート、モデルの保存/ロード。

ML.NET

ML.NET は Microsoft の .NET 機械学習フレームワーク。F# からもスムーズに使える。

open Microsoft.ML
open Microsoft.ML.Data

[<CLIMutable>]
type HouseData = {
    Size: float32
    Price: float32
}

[<CLIMutable>]
type Prediction = {
    [<ColumnName("Score")>]
    Price: float32
}

let mlContext = MLContext()

let trainingData = [
    { Size = 1.1f; Price = 1.2f }
    { Size = 1.9f; Price = 2.3f }
    { Size = 2.8f; Price = 3.0f }
    { Size = 3.4f; Price = 3.7f }
]

let dataView = mlContext.Data.LoadFromEnumerable trainingData

let pipeline =
    mlContext.Transforms
        .Concatenate("Features", "Size")
        .Append(mlContext.Regression.Trainers.Sdca(labelColumnName = "Price", maximumNumberOfIterations = 100))

let model = pipeline.Fit dataView

let predictor = mlContext.Model.CreatePredictionEngine<HouseData, Prediction>(model)

let size = { Size = 2.5f; Price = 0f }
let prediction = predictor.Predict size
printfn "Predicted price for size %f: %f" size.Size prediction.Price

ML.NET は勾配ブースティング、ランダムフォレスト、ロジスティック回帰、レコメンダ、テキスト分類、画像分類など幅広いアルゴリズムをサポート。TensorFlow / ONNX モデルのインポートも可能。

F# の [<CLIMutable>] 属性は、ML.NET が要求する setter を生成する(F# のレコードはデフォルトでイミュータブル)。


15. F# in Azure Functions / AWS Lambda

Azure Functions

F# の Isolated Worker モデルは .NET 9 で標準だ。

namespace MyApp

open System
open Microsoft.Azure.Functions.Worker
open Microsoft.Azure.Functions.Worker.Http
open Microsoft.Extensions.Logging

type HelloFunction(logger: ILogger<HelloFunction>) =

    [<Function("Hello")>]
    member _.Run
        ([<HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")>] req: HttpRequestData)
        =
        logger.LogInformation "F# HTTP trigger function processed a request"
        let response = req.CreateResponse(System.Net.HttpStatusCode.OK)
        response.WriteString "Hello from F# on Azure Functions"
        response

Microsoft 自身が F# を Azure Functions の一級言語として扱う。func init --worker-runtime dotnet-isolated --language fsharp でテンプレート生成。

AWS Lambda

AWS の .NET 6/8 ランタイムで F# Lambda を動かせる。

namespace MyLambda

open Amazon.Lambda.Core

[<assembly: LambdaSerializer(typeof<Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer>)>]
do ()

type Handler() =
    member _.Hello (input: string) (_: ILambdaContext) : string =
        sprintf "Hello %s from F# Lambda" input

Amazon.Lambda.Tools CLI でデプロイ。大規模な会社ではクラウド自動化スクリプトを F# で書く事例がある。


16. Donald / Suave / Hopac / FParsec — その他

Donald — 薄い SQL クライアント

Donald は ADO.NET の上に乗った薄い SQL ヘルパー。EF Core のような ORM ではなく、SQL をそのまま書いて結果を強い型のレコードにマップする 方式。

open Donald

let conn = new System.Data.SqlClient.SqlConnection(connStr)

let sql = "SELECT id, name, email FROM users WHERE active = 1"

type User = { Id: int; Name: string; Email: string }

let readUser (rd: System.Data.IDataReader) =
    { Id = rd.ReadInt32 "id"
      Name = rd.ReadString "name"
      Email = rd.ReadString "email" }

let users =
    conn
    |> Db.newCommand sql
    |> Db.query readUser

LINQ も ORM も嫌で SQL のまま書きたいとき。

Suave

Suave は Henrik Feldt が作った。自前 HTTP サーバ + ルーティングライブラリで、Saturn や Giraffe より前(2014 年頃)から存在する。特徴は ASP.NET Core の上ではない独立した HTTP サーバ であること。小さなサイドプロジェクトで人気があった。

open Suave
open Suave.Filters
open Suave.Operators
open Suave.Successful

let app =
    choose
        [ GET >=> path "/" >=> OK "Hello, Suave"
          GET >=> pathScan "/user/%d" (fun id -> OK (sprintf "User %d" id)) ]

startWebServer defaultConfig app

2026 年では新規プロジェクトはほぼ Giraffe/Saturn を選ぶが、小さな CLI に HTTP インターフェイスを足すときの軽い選択肢としては残っている。

Hopac

Hopac は Vesa Karvonen が作った並行性ライブラリ。Concurrent ML / Reppy の channels-and-jobs モデルを F# に移したもの。

open Hopac
open Hopac.Infixes

let producer (ch: Ch<int>) =
    Job.forUpToIgnore 0 9 (fun i -> Ch.give ch i)

let consumer (ch: Ch<int>) =
    Job.forUpToIgnore 0 9 (fun _ ->
        Ch.take ch >>= fun v ->
        Job.unit (printfn "Received: %d" v))

job {
    let ch = Ch<int>()
    do! Job.start (producer ch)
    do! consumer ch
}
|> run

Job は軽量スレッド。チャネルベースのメッセージパッシング、同期通信、選択(Alt)が Concurrent ML そのまま。

async/Task では表現力が足りないとき、高性能なメッセージパッシングが必要なときに使う。Jet.com がプライシングエンジンの一部に Hopac を使った話が有名。

FParsec

FParsec は Stephan Tolksdorf による Parsec(Haskell のパーサコンビネータ)の F# 移植。

open FParsec

let pInteger : Parser<int, unit> = pint32
let pPlus = pchar '+' >>. spaces

let pSum =
    pInteger .>>. (pPlus >>. pInteger)
    |>> (fun (a, b) -> a + b)

let result = run pSum "12 + 30"
match result with
| Success (v, _, _) -> printfn "Sum = %d" v
| Failure (err, _, _) -> printfn "Parse error: %s" err

LL(1) 以上のバックトラックパーサを簡単に作れる。DSL、設定ファイルパーサ、ドメイン特化言語を作るときの標準ツール。


17. 韓国 / 日本 — 韓国の .NET エンタープライズ, Usac, MS Japan

韓国

韓国の F# コミュニティは正直小さい。.NET 自体、韓国ではゲームサーバ(特に Unity バックエンド)、金融の一部、公共系 SI に集中する。F# はその中の一部の会社で、ドメインモデリングやデータパイプラインの道具として使われる。

  • Kakao / Line の一部データ分析スクリプト — F# が Polyglot Notebooks 経由で ad-hoc 分析に使われる例がある(公式発表はなし、カンファレンスのサイドトークでよく出る話)。
  • NHN, Netmarble, Pearl Abyss などゲーム会社の一部バックオフィスツール。
  • 金融 — 一部証券・資産運用会社でモデリング道具として F# が使われている例があるが、公開のケーススタディは少ない。
  • MSDN.kr / .NET Korea User Group — Facebook グループと Discord。F# 単独の韓国コミュニティは存在せず、.NET 全体のコミュニティの中で F# の話が出る。

韓国語に翻訳された F# の本はほぼない。Don Syme の Expert F# 英語版か Stylish F# 英語版を読むのが普通。

日本

日本の F# コミュニティは韓国より厚い。

  • ユーザックシステム (Usac System) — 東京・大阪・名古屋の RPA / 物流自動化の会社。自社プロダクトの一部を F# で書いている。Microsoft Japan の F# エバンジェリスト川上和也さん(@kos59125)がよく言及する。
  • F# Tokyo — 年次のユーザーミートアップ。年によっては 100 人規模で集まる。
  • F# Online Meetup Japan — コロナ以降オンライン中心になり、2022 年から定期開催。
  • Microsoft Japan の F# エバンジェリスト — Microsoft Japan は日本の .NET コミュニティで F# を継続的にプッシュしてきた。横田一久さん、川上和也さんがその席にいた。
  • 凸版印刷 (Toppan Printing), NTT データの一部 — 社内ツール・分析パイプラインで F# 利用事例が報告されたことがある。

日本語の F# 資料は韓国語よりずっと多い。Qiita の fsharp タグには数百件の記事がある。Don Syme の本も日本語訳版が存在する。


18. 誰が F# を学ぶべきか

正直に。

学んでおくと得な人

  • .NET バックエンドを書く C# 開発者 — 同じ BCL、同じランタイム、同じ NuGet パッケージを使いながら、関数型スタイルとドメインモデリングを得られる。C# 9 で入った records、pattern matching、switch expressions はほぼ F# 由来。F# を知ると C# がどこへ向かっているかが先に見える。
  • 金融・保険・物流・ヘルスケアのモデラー — discriminated union でドメインを表現する力は他の言語と次元が違う。「不正な状態を表現不可能にする」という Scott Wlaschin のスローガンが本当に成り立つ。
  • OCaml / Haskell を知っているが業界で使える会社が見つからなかった人 — F# は ML 系の親戚で、.NET という巨大な産業基盤の上で動く。「自分の関数型の知識をどこで使うか」の答えになる。
  • データ分析を強い型で行いたい人 — type provider は本当に別次元のツールだ。

学ばなくていい人

  • .NET を絶対使わない人 — F# は .NET の上で動く。.NET を使わないなら、Haskell, OCaml, Scala の方が合理的。
  • 純粋性に強くこだわる関数型マニア — F# はマルチパラダイム。可変性も許す。OOP クラスも書ける。Haskell のような純粋性が欲しいならがっかりする。
  • 学習曲線の短さを最優先する人 — F# 自体は難しくないが、「C# と BCL と ASP.NET Core を知らずに F# だけ学ぶ」のは事実上不可能。.NET エコシステムごと付いてくる。

F# の本当の価値は 「.NET という巨大な産業インフラの上で ML スタイルの関数型ドメインモデリングをする」 ことにある。この組み合わせに魅力を感じるなら、学ぶ価値は十分ある。


19. 参考 / References

  • F# 9 発表 — devblogs.microsoft.com/dotnet/announcing-fsharp-9
  • F# 言語リファレンス — learn.microsoft.com/dotnet/fsharp/language-reference
  • F# Foundation — fsharp.org
  • .NET 9 発表 — devblogs.microsoft.com/dotnet/announcing-dotnet-9
  • F# GitHub — github.com/dotnet/fsharp
  • Saturn — saturnframework.org
  • Giraffe — giraffe.wiki
  • Bolero — fsbolero.io
  • Fable — fable.io
  • Feliz — zaid-ajaj.github.io/Feliz
  • Elmish — elmish.github.io
  • Avalonia.FuncUI — funcui.avaloniaui.net
  • Avalonia — avaloniaui.net
  • Fantomas — fsprojects.github.io/fantomas
  • Paket — fsprojects.github.io/Paket
  • FAKE — fake.build
  • Polyglot Notebooks — code.visualstudio.com/docs/polyglot
  • FSharp.Data — fsprojects.github.io/FSharp.Data
  • MathNet.Numerics — numerics.mathdotnet.com
  • DiffSharp — diffsharp.github.io
  • TorchSharp — github.com/dotnet/TorchSharp
  • ML.NET — dotnet.microsoft.com/apps/machinelearning-ai/ml-dotnet
  • Donald — github.com/pimbrouwers/Donald
  • Suave — suave.io
  • Hopac — github.com/Hopac/Hopac
  • FParsec — www.quanttec.com/fparsec
  • F# in Azure Functions — learn.microsoft.com/azure/azure-functions/functions-reference-fsharp
  • SAFE Stack — safe-stack.github.io
  • F# Software Foundation Slack — fsharp.org/guides/slack
  • F# Tokyo — fsugjp.connpass.com
  • Don Syme blog — dsyme.github.io
  • Scott Wlaschin — Domain Modeling Made Functional — fsharpforfunandprofit.com
  • Krzysztof Cieslak — Ionide / Saturn — kcieslak.io