F#を極めたい方向けの初心者向けチュートリアル

# F#：.NETのための強力な関数型優先言語

## 第1章：F#の紹介

F#（エフシャープと発音）は、関数型、命令型、オブジェクト指向のパラダイムを組み合わせた多用途のオープンソースプログラミング言語です。Microsoft Researchによって開発され、.NETプラットフォーム上で動作し、表現力、型安全性、パフォーマンスのユニークな組み合わせを提供します。

F#の特徴：
- 関数型プログラミング
- 型推論
- 簡潔な構文
- .NETプラットフォームとの互換性

簡単な「Hello, World!」プログラムから始めましょう：

```fsharp
printfn "こんにちは、世界！"
```

## 第2章：基本的な型と値

F#はさまざまなデータ型をサポートしています。整数、浮動小数点数、文字列、ブール値などを見てみましょう：

```fsharp
let integerNumber = 42
let floatingPointNumber = 3.14
let text = "F#は素晴らしい言語です"
let isAwesome = true

printfn "整数: %d" integerNumber
printfn "浮動小数点数: %f" floatingPointNumber
printfn "文字列: %s" text
printfn "真偽値: %b" isAwesome
```

## 第3章：関数

F#では関数がファーストクラスの市民です。円の面積を計算する簡単な関数を作成してみましょう：

```fsharp
let calculateCircleArea radius =
    let pi = System.Math.PI
    pi * radius * radius

let area = calculateCircleArea 5.0
printfn "円の面積: %.2f" area
```

## 第4章：パターンマッチング

パターンマッチングは、F#でデータ構造を分解するための強力な機能です：

```fsharp
let describeNumber n =
    match n with
    | 0 -> "ゼロです"
    | x when x < 0 -> "負の数です"
    | x when x % 2 = 0 -> "偶数です"
    | _ -> "正の奇数です"

printfn "%d: %s" 0 (describeNumber 0)
printfn "%d: %s" -5 (describeNumber -5)
printfn "%d: %s" 4 (describeNumber 4)
printfn "%d: %s" 7 (describeNumber 7)
```

## 第5章：リストとシーケンス

F#はコレクションを扱うための強力なツールを提供します：

```fsharp
let numbers = [1; 2; 3; 4; 5]
let squares = List.map (fun x -> x * x) numbers

printfn "元のリスト: %A" numbers
printfn "二乗したリスト: %A" squares

let evenNumbers = List.filter (fun x -> x % 2 = 0) numbers
printfn "偶数のみ: %A" evenNumbers
```

## 第6章：再帰

再帰はF#でアルゴリズムを表現する自然な方法です：

```fsharp
let rec factorial n =
    match n with
    | 0 | 1 -> 1
    | _ -> n * factorial (n - 1)

let result = factorial 5
printfn "5の階乗: %d" result
```

## 第7章：判別共用体

判別共用体を使用すると、複数のケースを持つ型を定義できます：

```fsharp
type Shape =
    | Circle of radius: float
    | Rectangle of width: float * height: float
    | Triangle of base': float * height: float

let calculateArea shape =
    match shape with
    | Circle radius -> System.Math.PI * radius * radius
    | Rectangle (width, height) -> width * height
    | Triangle (base', height) -> 0.5 * base' * height

let circleArea = calculateArea (Circle 5.0)
let rectangleArea = calculateArea (Rectangle(4.0, 3.0))
let triangleArea = calculateArea (Triangle(6.0, 4.0))

printfn "円の面積: %.2f" circleArea
printfn "長方形の面積: %.2f" rectangleArea
printfn "三角形の面積: %.2f" triangleArea
```

## 第8章：レコード型

レコード型を使用すると、名前付きフィールドを持つ構造化されたデータを作成できます：

```fsharp
type Person = { Name: string; Age: int; City: string }

let alice = { Name = "Alice"; Age = 30; City = "東京" }
let bob = { Name = "Bob"; Age = 25; City = "大阪" }

let printPerson person =
    printfn "%s (%d歳) - %s在住" person.Name person.Age person.City

printPerson alice
printPerson bob
```

## 第9章：オプション型

オプション型は値の不在を扱うのに役立ちます：

```fsharp
let divideIfEven numerator denominator =
    if denominator % 2 = 0 then
        Some(numerator / denominator)
    else
        None

let printResult result =
    match result with
    | Some value -> printfn "結果: %d" value
    | None -> printfn "計算できません"

printResult (divideIfEven 10 4)
printResult (divideIfEven 10 3)
```

## 第10章：非同期プログラミング

F#は非同期プログラミングを簡単にします：

```fsharp
open System
open System.Net.Http

let fetchWebPageAsync (url: string) = async {
    use client = new HttpClient()
    let! response = client.GetStringAsync(url) |> Async.AwaitTask
    return response.Substring(0, 100) // 最初の100文字
}

let websites = [
    "https://fsharp.org";
    "https://docs.microsoft.com/ja-jp/dotnet/fsharp/";
]

let fetchAllPages = async {
    let! results = websites |> List.map fetchWebPageAsync |> Async.Parallel
    for (url, content) in List.zip websites results do
        printfn "%s: %s..." url content
}

Async.RunSynchronously fetchAllPages
```

## 第11章：単位of measure

F#では数値型に単位を追加できます：

```fsharp
[<Measure>] type m
[<Measure>] type s

let distance = 100.0<m>
let time = 9.58


let speed = distance / time
printfn "速度: %.2f m/s" speed

// 変換
[<Measure>] type km
[<Measure>] type h

let kmPerHour = (speed * 3600.0<s/h>) / 1000.0<m/km>
printfn "速度: %.2f km/h" kmPerHour
```

## 第12章：型プロバイダー

型プロバイダーを使用すると、外部データソースに簡単にアクセスできます：

```fsharp
#r "nuget: FSharp.Data"
open FSharp.Data

type Weather = JsonProvider<"https://api.openweathermap.org/data/2.5/weather?q=Tokyo&appid=YOUR_API_KEY">

let getWeather city =
    let apiKey = "YOUR_API_KEY"
    let url = sprintf "https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s" city apiKey
    let weather = Weather.Load(url)
    
    printfn "%s の天気:" city
    printfn "気温: %.1f°C" (weather.Main.Temp - 273.15)
    printfn "湿度: %d%%" weather.Main.Humidity
    printfn "天気: %s" weather.Weather.[0].Description

getWeather "Tokyo"
```

## 第13章：計算式

計算式を使用すると、カスタムの制御フローを定義できます：

```fsharp
type MaybeBuilder() =
    member this.Bind(x, f) =
        match x with
        | None -> None
        | Some a -> f a
    
    member this.Return(x) = Some x

let maybe = MaybeBuilder()

let divideBy bottom top =
    if bottom = 0 then None
    else Some(top / bottom)

let result = maybe {
    let! a = divideBy 2 10
    let! b = divideBy 2 a
    return b
}

match result with
| Some value -> printfn "結果: %d" value
| None -> printfn "計算できません"
```

## 第14章：オブジェクト指向プログラミング

F#はオブジェクト指向プログラミングの概念をサポートしています：

```fsharp
type Animal(name: string) =
    member this.Name = name
    abstract member MakeSound : unit -> string

type Dog(name: string) =
    inherit Animal(name)
    override this.MakeSound() = "ワンワン"

type Cat(name: string) =
    inherit Animal(name)
    override this.MakeSound() = "ニャーニャー"

let animals = [
    Dog("ポチ") :> Animal;
    Cat("タマ") :> Animal
]

for animal in animals do
    printfn "%s: %s" animal.Name (animal.MakeSound())
```

## 第15章：Giraffeを使用したWeb開発

F#はWeb開発にも使用できます。以下はGiraffeフレームワークを使用した簡単な例です：

```fsharp
#r "nuget: Giraffe"
#r "nuget: Microsoft.AspNetCore.App"

open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Hosting
open Giraffe

let webApp =
    choose [
        route "/" >=> text "F#とGiraffeへようこそ！"
        route "/hello" >=> bindQuery<string option> (fun name ->
            match name with
            | Some n -> text (sprintf "こんにちは、%s！" n)
            | None -> text "こんにちは、ゲスト！"
        )
    ]

[<EntryPoint>]
let main _ =
    Host.CreateDefaultBuilder()
        .ConfigureWebHostDefaults(
            fun webHostBuilder ->
                webHostBuilder
                    .Configure(fun app -> app.UseGiraffe webApp)
                    .Build()
                    .Run())
```

この包括的なガイドでは、F#プログラミングのさまざまな側面を基本的な概念から高度な機能まで網羅しています。各章にはコード例と説明が含まれており、学習者がF#の用語と概念を理解するのに役立ちます。これらの例を通じて学習することで、F#プログラミングの堅固な基礎を身につけ、より複雑なプロジェクトに取り組む準備が整います。