F# 入門：少しでも書けるようになるための記録

## はじめに

関数まつりというイベント先日参加して、F#について興味がでてきました。F#を少しでも書けるようになってみたいとおもい、ちょっと paiza で問題を解いてみたので、その時に学んだことをまとめたものです。これから F# を始めたい人などの参考になれば嬉しいです。

---

## F# って何がうれしいの？

F# は関数型プログラミングをベースにした .NET 向けの言語で、以下のような特徴があります：

* **関数型と命令型のハイブリッド**：関数型の利点を活かしつつ、現実のアプリ開発にも耐える柔軟性がある。
* **構文がシンプルで強力**：パイプ演算子（`|>`）やイミュータブルな変数などにより、ロジックがきれいに書ける。
* **非同期処理との親和性**：`async` や計算式（computation expression）を使えば、直感的に非同期コードが書ける。
* **ビルダー構文による柔軟な制御**：ビルダー（`builder`）を定義することで、独自の制御フローを作ることも可能。

F# は「現実寄り」の設計で、型の安全性を保ちつつも、扱いやすい構文を提供してくれます。

---

## はじめての出力

```fsharp
printfn "Hello, world"
```

* `printfn` は出力＋改行あり
* `printf` は出力のみ（改行なし）

```fsharp
printf "%d %d" 1 2
```

---

## リストの出力

```fsharp
[1; 2; 3] |> List.iter (printf "%d ")
```

* `List.iter` はリストの各要素に処理を適用
* `%d` は整数出力、`"%d "` とするとスペース付きで出力

ただし、最後にスペースが入ってしまうので、整形してキレイに出したいときは以下のように：

```fsharp
[1; 2; 3]
|> List.map string
|> String.concat " "
|> printfn "%s"
```

---

## 数値の範囲をリストにする

```fsharp
[1..10]  // 1 から 10 までの整数リスト
```

範囲指定付き：

```fsharp
[0..2..10]  // 0, 2, 4, 6, 8, 10
```

---

## 標準入力を受け取る

1行読み取り：

```fsharp
let input = System.Console.ReadLine()
printfn "%s" input
```

整数として読み取り：

```fsharp
let num = System.Console.ReadLine() |> int
```

複数行を受け取ってリストに：

```fsharp
let inputs = [ for _ in 1..2 -> System.Console.ReadLine() ]
inputs |> List.iter (printfn "%s")
```

* `for _ in 1..2 ->` は2回繰り返すリスト内包表現
* `_` は使わない変数名

---

## リストの構造をそのまま出力したいとき

```fsharp
printfn "%A" [1; 2; 3]
```

* `%A` は F# のオブジェクトを構造ごと表示してくれる（デバッグ用によく使う）

---

## 配列を使った繰り返し

```fsharp
[|1; 2; 3|] |> Array.iter (printfn "%d")
```

* 配列は `[| |]` で作る
* `Array.iter` は `List.iter` と同様に使える

スペースで区切られた文字列を1行ずつ出力：

```fsharp
System.Console.ReadLine().Split()
|> Array.iter (printfn "%s")
```

---

## 条件分岐（if 文）

```fsharp
let x = 10
if x > 5 then
    printfn "x は 5 より大きい"
else
    printfn "x は 5 以下"
```

---

## 論理演算子（AND / OR / NOT）

```fsharp
let a = true
let b = false

if a && not b then
    printfn "a は真、b は偽"

if a || b then
    printfn "どちらかが真"
```

* `&&` は AND
* `||` は OR
* `not` は 否定（NOT）

---

## よく使った関数・構文まとめ

### とりあえず役立ちs組み込み関数・メソッド

| 名前                          | 説明                        |
| --------------------------- | ------------------------- |
| `List.map`                  | リストの各要素を変換して新しいリストを返す     |
| `List.iter`                 | 各要素に副作用のある処理を適用（出力など）     |
| `List.filter`               | 条件に合う要素だけを残すリストを返す        |
| `List.sum`                  | 数値リストの合計を返す               |
| `List.max` / `List.min`     | 最大値・最小値を返す                |
| `Array.map`, `Array.iter`   | 配列版の map / iter           |
| `System.Console.ReadLine()` | 1行入力を取得                   |
| `string.Split()`            | 文字列を区切って配列に変換             |
| `int`, `float`, `bool`      | 型変換：文字列から数値・真偽値などに変換      |
| `String.concat`             | 文字列配列を指定区切り文字で連結する        |
| `sprintf`                   | 書式付きの文字列を作る（出力せず文字列として返す） |

---

### フォーマット指定子まとめ（printf 系）

| 指定子                         | 説明                             |           |       |
| --------------------------- | ------------------------------ | --------- | ----- |
| `%d`                        | 整数（int）を出力                     |           |       |
| `%s`                        | 文字列（string）を出力                 |           |       |
| `%f`                        | 浮動小数点数（float）を出力               |           |       |
| `%b`                        | ブール値（bool）を出力（true / false）    |           |       |
| `%A`                        | 任意の型を構造表示（Debug用、ToString風）    |           |       |
| `%c`                        | 1文字（char）を出力                   |           |       |
| `%o`                        | 8進数で整数を出力                      |           |       |
| `%x`                        | 16進数で整数を出力（小文字）                |           |       |
| `%X`                        | 16進数で整数を出力（大文字）                |           |       |
| `%%`                        | パーセント記号（%）を出力                  |           |       |
| 構文・関数                       | 説明                             |           |       |
| --------------------------  | ------------------------------ |           |       |
| `printf`, `printfn`         | 出力（改行なし/あり）                    |           |       |
| `List.iter`, `Array.iter`   | 各要素に関数を適用                      |           |       |
| `List.map string`           | 各要素を文字列に変換                     |           |       |
| `String.concat " "`         | 文字列をスペースで結合                    |           |       |
| `System.Console.ReadLine()` | 標準入力1行読み取り                     |           |       |
| `int`                       | 文字列を整数に変換                      |           |       |
| `%d`                        | 整数出力（int）                      |           |       |
| `%s`                        | 文字列出力（string）                  |           |       |
| `%A`                        | 任意の構造体出力（自動変換）                 |           |       |
| `if ... then ... else`      | 条件分岐                           |           |       |
| `&&`, \`                    |                                | `, `not\` | 論理演算子 |

---

## 最後に

F# は最初こそ独特に見えるけど、パターンをつかむとすごくスッキリ書ける言語かなとおもいました。

関数型でありながら純粋性を強制しない柔軟さを持ち、.NET 言語としての相互運用性や現実的な開発体験を意識した設計が魅力のようです。

これからも `async` 処理や DSL 的な構文、さらに型システムの応用にも挑戦していきたいと思います！

---

株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら
[https://www.wantedly.com/companies/xincere-inc/stories](https://www.wantedly.com/companies/xincere-inc/stories)
弊社には年間100人程度の実務未経験の方に応募いただき、技術面接を実施しております。
この記事が少しでも学びになったという方は、ぜひ wantedly のストーリーもご覧いただけるととても嬉しいです！