純粋値型Swift

これは [Swift Tweets 2017 Summer](https://swift-tweets.github.io/2017-summer) での発表を編集したものです。

---

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">それでは、&quot;純粋値型Swift&quot;というタイトルで発表します。 <a href="https://twitter.com/hashtag/swtws?src=hash">#swtws</a> <a href="https://t.co/maVe3JYmM8">pic.twitter.com/maVe3JYmM8</a></p>&mdash; koher (@koher) <a href="https://twitter.com/koher/status/888755607674564608">2017年7月22日</a></blockquote>

Swift は値型を中心とした言語です。この発表では、仮に参照型を使わずに値型だけを使った場合、 Swift でどれだけのことができるかを探ります。

Swift が登場した当初、僕は Swift が値型を中心としていることに驚きました。参照型でないとできないことがあるし、比較的新しい言語は値型を参照型に見せかけてすべてが参照型であるかのように振る舞うことが多いように感じていたからです。

しかし、 Swift を使うにつれて、値型だけでできることは当初考えていたよりもずっと幅広いことがわかってきました。また、値型の特性を活かすことで、参照型では面倒なケースでコードを簡潔に保てることもわかってきました。

Swift が最も利用されている iOS アプリ開発では、 `UIKit` 等の Objective-C 由来の Framework に引っ張られて参照型中心のプログラミングになってしまうことが多いと思います。

そのため、せっかく値型中心の言語なのに Swift で実際に値型中心のプログラミングをしている人は多くないように思います。この発表を通して、値型中心でプログラミングをすることに対して興味を持っていただけるとうれしいです。

## 参照型で起こりがちな問題

まず初めに、値型だと何がうれしいのかを説明するために、参照型で辛いケースをいくつか紹介します。

### ケース1

次のコードを実行したとき何が起こるでしょうか？最後の行で `age` をインクリメントしていますが、その結果は `group` に反映されるでしょうか？

```swift
class User {
  let name: String
  var age: Int
  init(...) { ... }
}

let owner: User = group.owner
owner.age += 1 // 何が起こる？
```

答えは「わからない」です。 `group.owner` の実装によります。内部に保持している `User` インスタンスをそのまま返していれば反映されますし、それを避けるためにインスタンスをコピーして返していれば反映されません。

このように、ミュータブルな参照型のインスタンスを取り回すと、状態が共有されるのかを型で表現することができません。つまり、コメントやドキュメントで管理しなければならないということです。裏を返せば、状態の共有について曖昧にできる余地があるということです。 `owner` を変更したらそれが `group` に反映されるかもしれないしされないかもしれない、でも多くのコードでは関係ないから気にしない、そんな状況です。

**これは確信を持って言えることですが、仕組み上曖昧にできるものはいつか必ず曖昧になります。** ドキュメントに記載していたとしても、一箇所でも更新されてない箇所があれば、もはや全体が信頼できなくなります。

個別にドキュメントするのではなく、オブジェクトを `return` するときには必ずコピー（防御的コピー）するポリシーに統一するとどうでしょう？当初はうまく機能するかもしれません。しかし、ディープコピーでなくシャローコピーになっている箇所があったら？利用しているライブラリのポリシーが異なったら？開発を引き継いだ人がポリシーを理解していなかったら？緊急対応時にコピーを忘れてしまったら？機械的な保証なしに、常にプロジェクト全体でミスが一つもなくポリシーが守られていると自信を持てるでしょうか。多大な労力を支払って人力でチェックをすれば100%ではなくてもある程度の保証はできるかもしれません。しかし、それでもなお不安は残ります。機械に任せることができれば、ノーコストで曖昧さをなくし、安心・安全を手に入れることができます。

曖昧さの原因はミスだけではありません。パフォーマンスの問題でコピーが許容できない箇所で意図的にコピーを避けるかもしれません。一箇所でも例外を設けると常に例外を意識しなければならなくなります。そして、例外はドキュメントに記し、メンテを漏らしてはいけません。

値型であればそのような問題は起こりません。状態が共有されることがあり得ないからです。先の例で `User` が `struct` だったら、実装によらず `age` の変更が `group` に反映されることはありません。

```swift
struct User {
  let name: String
  var age: Int
}

var owner: User = group.owner
owner.age += 1 // group には反映されない
```

### ケース2

参照型でもイミュータブルな型を使ってそのような問題に対処できます。イミュータブルな型のインスタンスは変更することができないので、コピーを返さずそのインスタンスそのものを返しても、共有された状態が変更されてしまうことはありません。

Haskell のように言語全体でイミュータブルという例もありますが、そこまでしなくてもミュータブルな範囲を最小限に留めイミュータブル中心のコードにすることで、状態が共有されてしまう問題を気にせずにコードを書ける範囲を広げられます。

イミュータブルな型を使う場合には、値を書き換えたい場合にはインスタンスごと作り変えます（↓のコードで `user` が `var` なのはイミュータビリティとは関係なく変数か定数かの話です。異なる概念なので注意して下さい）。

```swift
class User {
  let name: String
  let age: Int // let にして User をイミュータブルに
  init(...) { ... }
}

var user: User = ...
// インスタンスを作り変えて値を更新
user = User(name: user.name, age: user.age + 1)
```

しかし、先程のように `group` の中の `age` を変更したいとするとどうなるでしょう？ `Group` もイミュータブルな `class` だとすると次のようになります。さすがに面倒です。

```swift
var group: Group = ...
var owner: User = group.user
owner = User(name: owner.name, age: owner.age + 1)
group = Group(..., owner: owner, ...)
```

値型なら簡単です。もし `Group` と `User` が `struct` なら次のように書けます。たとえ `group` と `user` が `var` にして変更可能にしても、値型であれば共有された状態が変更されることはありません。

```swift
group.user.age += 1
```

余談ですが、イミュータブルな世界でこれを簡単にするために編み出された Lens という手法があります。去年の [&#064;tryswiftconf](https://twitter.com/tryswiftconf) のスピーカーである [&#064;chriseidhof](https://twitter.com/chriseidhof) さんが[解説している](http://chris.eidhof.nl/post/lenses-in-swift/)ので紹介します。

さて、今のコードの書き換えは示唆的です。イミュータブルな `class` を使って書かれたコードが `struct` を使ったコードに書き換えられました。これは、 **イミュータブルな `class` とミュータブルな `struct` が対応する** ことを示しています。

値型では代入時に値がコピーされるためインスタンスが共有されません。そのため、次のように `b` を書き換えても `a` が影響を受けることはありません。イミュータブルな参照型のコードと対応しているのがわかると思います。

```swift
// 値型
var a: User = ...
var b: User = a
b.age += 1 // a は変更されない

// 参照型（イミュータブル）
var a: User = ...
var b: User = a
b = User(name: b.name, age: b.age + 1) // a は変更されない
```

この対応については僕や @omochimetaru が過去に投稿しているので詳しくはそちらを御覧ください。

- [SwiftのArrayがミュータブルでもCovariantな理由](http://qiita.com/koher/items/81767a345d5ed53c04b7#swift%E3%81%AEarray%E3%81%8C%E3%83%9F%E3%83%A5%E3%83%BC%E3%82%BF%E3%83%96%E3%83%AB%E3%81%A7%E3%82%82covariant%E3%81%AA%E3%81%AE%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%8B)
- [Swift の struct の stored property は var にしよう](http://qiita.com/omochimetaru/items/7265e440418b38088ccb)

ミュータブルな値型とイミュータブルな参照型が等価だということは、値型を使えばイミュータブルと等しい安全性を手に入れられるということです。しかも、値を更新するときに面倒なことをする必要はありません。素晴らしいですね！

なお、他の言語に目を向ければ、たとえば Kotlin の `data class` では更新のためのメソッドを自動生成してくれるなど、イミュータブルプログラミングの負担を軽減してくれる言語機能があったりします。

```kotlin
// Kotlin
// val は Swift の let に相当
data class User(val name: String, val age: Int)

var user = User(name = "name", age = 42)
// copy は指定されたプロパティが更新された新しいインスタンスを返すメソッド
user = user.copy(age = user.age + 1)
```

しかし、幾分か軽減されたとはいえ、ネストされた値を更新しようとすると面倒だし、可読性も低いです。

```kotlin
// Kotlin
group = group.copy(owner = group.owner.let { it.copy(age = it.age + 1) })
```

再掲しますが、 `struct` だと↓です。

> ```swift
group.user.age += 1
```

### ケース3

参照型でミュータブルな世界とイミュータブルな世界を分けるためには、両方でほしいものは二重に実装して使い分ける必要があるということです。その代表格がコレクションです。

ミュータブルなコレクションとイミュータブルなコレクションを別々の `class` で実装することを考えてみましょう。このとき気をつけないといけないのは、イミュータブルなコレクションを継承してミュータブルなコレクションを作ってはいけないということです。イミュータブルなコレクションを継承して `append` 等のメソッドを追加してしまってはいけません。まさにそのような関係になってしまっているのが `NSArray` と `NSMutableArray` です。 `NSArray` クラスのインスタンスはイミュータブルですが、 `NSArray` 型変数には `NSMutableArray` のインスタンスも代入できるため、 `NSArray` 型としてはイミュータブルであることを保証できません。

では、派生関係のない完全に独立な `class` としてそれらを実装すれば良いのでしょうか。しかし、ミュータブル／イミュータブルなコレクションをまとめて取り扱いたいこともあるはずです。そのためには、次のように共通のスーパータイプが必要になります。なお、 `ImmutableList` が `final` になっているのは、継承を許すとミュータブルなサブタイプが作れてしまうからです。

```java
// Java
interface List<T> { ... } // 共通のスーパータイプ
final class ImmutableList<T> implements List<T> { ... }
class MutableList<T> implements List<T> { ... }
```

値型だとこのような三つの型は必要なく、一つの型で済ませられます。 `var` か `let` かでミュータビリティをコントロールできますし、 `var` であっても共有された状態が変更されてしまうことはありません。

コレクションは標準ライブラリが用意してくれるので、多重実装が必要でも特に面倒なことはないと思うかもしれません。しかし、同じことは自作の型でも起こります。

たとえば、僕は [EasyImagy](https://github.com/koher/EasyImagy) という、画像を簡単に扱うためのライブラリを作っています。次のように簡単に画像を取り扱えるものですが、特筆すべきはこの `Image` が `struct` で実装されており値型なことです。

```swift
var image = Image<RGBA>(named: "ImageName")!

print(image[x, y])
image[x, y] = RGBA(red: 255, green: 0, blue: 0, alpha: 127)
image[x, y] = RGBA(0xFF00007F) // red: 255, green: 0, blue: 0, alpha: 127

// Iterates over all pixels
for pixel in image {
    // ...
}
```

値型なので、 `Array` などと同じく、 `Image` は `var` ならミュータブルに、 `let` ならイミュータブルになります。三つの型は必要ありません。一つで十分です。

### 小まとめ

- 参照型では状態共有問題を避けるためにイミュータブルを使う
- イミュータブルには特有の煩わしさがある
- 値型はイミュータブルな参照型と似ている
- 値型なら状態共有の問題もなく更新も簡単

## 値型の問題と解決策

値型は確かに、状態の共有に関するややこしい問題を回避するという点では優れています。しかし、値型ならではの次のような問題もあります。

- コピーにコストがかかる
- 継承してサブタイプを作れない

コピーコストについては、値のサイズが大きければ大きいほど問題は深刻になります。値型の値は代入される度に丸ごとコピーされます。もし、 100 万個の要素を持つコレクションを引数に渡しただけで 100 個の要素分のコピーが実行されるならとても実用には耐えません。

継承については、オブジェクト指向言語において継承によるサブタイピングは抽象化を実現するための中心的な手段です。抽象化できないコードは冗長になり、メンテも難しくなります。

### コピーコストについて

Swift のコレクション（ `Array`, `Set`, `Dictionary` など）は Copy-on-write （以下 COW ）という仕組みによってコピーコストを最小限に留めています。

たとえば、次のコードでは `Array` は値型であるにも関わらず代入の時点ではコピーは発生しません（厳密には、 `Array` という `struct` のコピーは発生しますが、そこから参照されているバッファのコピーは発生しません）。

```swift
let a = [2, 3, 5, 7]
var b = a // ここでコピーは発生しない
print(b)
```

しかし、次のように `b` を変更しようとすると、その時点で `b` はバッファのコピーを作成し、自分が参照するバッファをコピーしたものに差し替えます。

```swift
let a = [2, 3, 5, 7]
var b = a // ここでコピーは発生しない
print(b)
b[2] = 4 // ここでコピーが発生する
```

`b` に `a` が代入された時点では `a` と `b` はバッファを共有していますが、 `b` を変更しようとした瞬間に `b` がバッファのコピーを作成し、共有をやめるわけです。

COW がおもしろいのは、次のように `b` を再度変更してもコピーが発生しないことです。

```swift
let a = [2, 3, 5, 7]
var b = a // ここでコピーは発生しない
print(b)
b[2] = 4 // ここでコピーが発生する
b[3] = 5 // ここではコピーは発生しない
```

このとき、 `a` と `b` はそれぞれ別々のバッファを参照しており、それらは共有されていません。そのため `b[3] = 5` でバッファを直接書き換えてしまっても共有状態が書き換えられてしまうことはなく、 `Array` の値型としての振る舞いに問題は起こりません。

このような仕組みで、Swiftはコレクションのような巨大な値でもコピーコストを避けながら値型として振る舞わせているわけです。

先程紹介した EasyImagy でもこの特性を活かしています。画像のような巨大な値をイミュータブルな `class` で表現しようとすると変更の度にとんでもないコストがかかってしまいます。

```swift
// Image がイミュータブルな class の場合
var image = image.updatePixel(newPixel, at: x, y) // 1ピクセルのために画像丸ごと再生成
```

また、イニシャライザで防御的コピーをすると、（数百万画素の画像なら）数百万要素を無駄にコピーしてしまうこともあります。

```java
// Java
// Image がイミュータブルな class でコレクションが参照型の場合
class Image<Pixel> {
  private List<Pixel> pixels;
  public Image(int width, int height, List<Pixel> pixels) {
    ...
    this.pixels = new ArrayList<>(pixels); // 防御的コピー
  }
}
```

`Image` に渡す `pixels` は型の上ではミュータブルだとしても実は変更されないかもしれません。しかし、 `Image` をイミュータブルに保つには防御的コピーで先行してコストを支払わなければなりません。コレクションが値型で COW なら本当に必要になるまでコピーを遅延できます。

COW に関しては、 "ライブコーディングでArrayを実装してCopy-on-writeの挙動を理解する" というタイトルで [iOSDC](https://iosdc.jp/2017/) に応募しているので、採用されれば9月に詳しく話すことになるかもしれません。

### 継承とサブタイピングについて

前置きが長くなりましたがここからが本題です。オブジェクト指向にどっぷり浸かった身としては、継承なしでどこまでコードが書けるのか不安になります。

実は、 Swift では値型でもプロトコルを使えばサブタイピングができます。次のような `Animal` , `Cat`, `Dog` を考えてみましょう。

```swift
protocol Animal { ...}
struct Cat: Animal { ... }
struct Dog: Animal { ... }
```

なお、前に `Animal` や `Cat` を使って説明したら昔ながらのオブジェクト指向みたいだと言われたので一応断っておきますが、オブジェクト指向を知らない人に `Animal` や `Cat` を使って継承の説明するのとは話が違います。オブジェクト指向を理解している人に対する説明で、型の派生関係だけが必要なときは、 `Animal` や `Cat`, `Dog` は、どれがスーパータイプでどれがサブタイプがひと目でわかるという意味で優れていると思います。（おことわり終わり）

プロトコルを使えば、値型である `Cat` や `Dog` であっても、抽象型であるAnimalとして値を取り回し処理を記述することができます。

```swift
func useAnimal(_ animal: Animal) { ... }
```

しかし、今は試しにプロトコル型の変数（や引数、戻り値）を作ることも禁止してみましょう（ `Animal` というプロトコルを作るのは OK だけど、 `Animal` 型変数は禁止）。サブタイピングによるポリモーフィズムがない、そんな世界です。これはトリッキーな制約ではなくて、 Swift では `associatedtype` を持ったプロトコル型の変数を作ることができません（ Swift 4 時点）。（ `associatedtype` 等を持たない）普通のプロトコルにだけそれが許可されていることの方が奇妙だとも言えます。

このような状態（値型しか使わず、プロトコル型変数も使わない）の Swift を **「純粋値型Swift」** と呼ぶことにしましょう。

「純粋値型Swift」では、プロトコルである `Animal` 型変数が使えません。それだと、一見 `Cat` と `Dog` を抽象的に扱うコードが書けないように思います。抽象化できないとコードが冗長になるので困ります。しかし、 `Animal` 型変数自体が使えなくても、実はジェネリクスを使えば次のように抽象化することができます。

```swift
func useAnimal<A: Animal>(_ animal: A) { ... }
```

この `animal` の型は `Animal` ではなく `Animal` を満たす具象型 `A` となります。 `A` は `Animal` を満たすので、 `Animal` のメソッドはすべて使えることとなり、 `Animal` を引数に受けた場合と同じようにコードを記述することができます。

この方法を使えば、 `associatedtype` を持つプロトコルに対しても抽象的なコードを書くことができます。

```swift
// sequence から index 番目の要素を取り出す関数
func element<S: Sequence>(of sequence: S, at index: Int) -> S.Iterator.Element {
  precondition(index >= 0)
  var iterator = sequence.makeIterator()
  for _ in 0..<index {
    _ = iterator.next()
  }
  return iterator.next()!
}
```

いかがでしょう？サブタイプポリモーフィズムがなくても結構コードが書けそうな気持ちになってきませんか？

「純粋値型Swift」は Haskell とよく似ています。先程の話の通り、値型はイミュータブルな参照型と等価です。 Haskell ではすべてがイミュータブルです。また、「純粋値型Swift」と同じく Haskell にはサブタイピングがありません（ GHC という事実上標準となっている処理系の拡張を使えば `RankNTypes` を使って同様のことはできます）。しかし、それでも Haskell を使って問題なくコードを書くことができます。

これはつまり、「純粋値型Swift」でも相当のことは問題なく行えるということです。 Swift の標準ライブラリでも、プロトコル型で受けるものはほとんどなく、多くがジェネリクスを使った方法で実装されています。

しかも、ジェネリクスを使った方法にはパフォーマンス上の利点もあります。プロトコル型で値を取り回すと動的ディスパッチになってしまいますが、ジェネリクスであればスペシャライズして静的ディスパッチにできることがあります。

```swift
// 先程のジェネリックな element(of:at:) を
element(of: ["a", "b", "c"], at: 1)
// に対して↓を呼び出しているようにスペシャライズできる。
// <S: Sequence> が消えて S が [String] に置き換わっている。
func element(of sequence: [String], at index: Int) -> String {
  precondition(index >= 0)
  var iterator = sequence.makeIterator()
  for _ in 0..<index {
    _ = iterator.next()
  }
  return iterator.next()!
}
```

これなら `sequence` や `iterator` の型をコンパイル時にすべて決定できるので、それらに対するメソッドコールを（動的ディスパッチではなく）静的ディスパッチにすることができます。

値型だけを使うことで

- 動的ディスパッチによるオーバーヘッドの回避
- Haskell と同じような堅牢性
- 状態の更新のためにイミュータブルなオブジェクトを作り変えるコーディング上の煩わしさやオーバーヘッドの回避

が実現できるならおもしろくないですか？

## 補足的トピック

### 値型ならinoutが活きる

`inout` （参照渡し）はあまり使いみちがないと思われがちですが、値型と組み合わせることで威力を発揮します。

Swift 4 では `inout` を利用した新しい `reduce` が加わるのですが、それを使うとこれまで `[User]` から `id` → `User` の `[String: User]` を作るのに次のようにしないといけなかったのが、

```swift
var result: [Int: User] = [:]
for user in users {
    result[user.id] = user
}
```

このように書くことができるようになります。 `inout` のおかげでループを書かなくても高階関数／メソッドを使って値型を逐次編集できるということです。

```swift
let result = users.reduce(into: [Int: User]()) { $0[$1.id] = $1 }
```

これについては[こちらの投稿](http://qiita.com/koher/items/17636e95e18e529e5b9b)に詳しく書いたので御覧ください。

他にも、次のような `update` メソッドを用意すれば `map` で `Array` やその要素を作り変えなくても、ループを回すのと同じパフォーマンスで簡単に各要素の更新を実行することができます。

```swift
extension Array {
    public mutating func update(_ operation: (inout Element) throws -> ()) rethrows {
        for i in startIndex..<endIndex {
            try operation(&self[i])
        }
    }
}

array.update { $0.foo *= 2 }
```

### 値型と再帰の辛さ

値型で問題になるのが再帰した型を作れないことです。たとえば、次のような型は無限に再帰してしまい、サイズが発散してしまいます。

```swift
struct Foo {
  var bar: Int
  var foo: Foo // 無限に再帰する
}
```

再帰データ構造を表せないのは値型の弱点です。そのため Swift には `indirect` というキーワードがあります。次のようにして連結リストを作ることができます。

```swift
enum List<T> {
  case none
  indirect case some(T, List<T>)
}
```

`indirect` だと何が起こるのでしょうか？ Swift Programming Language には "insert the necessary layer of indirection" と[書かれています](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html)が、ヒープに領域が確保され値がコピーされるものと考えられます。

問題になるのが `struct` です。 `enum` では `indirect` が使えますが、 `struct` では `indirect` が使えません（ Swift 4 時点）。そのため、次のようなことはできません。

```swift
struct List<T> {
  let element: T
  indirect let next: List<T>?
}
```

`struct` で再帰をするには、次のような `Box` を作って一度 `indirect` を挟む必要があります。これはちょっと面倒です。

```swift
enum Box<T> {
  indirect case value(T)
}

struct List<T> {
  let element: T
  let next: Box<List<T>>?
}
```

再帰に関する煩わしさが生まれるのは、イミュータブルな参照型にはない値型のデメリットです。

### クロージャと状態の共有

Swiftで値型だけでコードを書こうとしたときの ~~最大の壁~~ やっかいなのがクロージャです。

（ @rintaro さんに教えていただいて、発表時から内容を変更しています。）

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">共有なくすだけなら { [a] in でキャプチャしちゃえばいいのでは。 <a href="https://twitter.com/hashtag/swtws?src=hash">#swtws</a></p>&mdash; Rintaro Ishizaki (@rintaro) <a href="https://twitter.com/rintaro/status/888761933775511553">2017年7月22日</a></blockquote>

Swift のクロージャ（や関数）は参照型です。純粋な関数であればイミュータブルなので参照型であっても値型のように振る舞うことに問題はありません。しかし、状態をキャプチャしたクロージャはそうはいきません。

たとえば、次のようなコードを書くとaという状態が共有されてしまいます。

```swift
var a: Int = 0

let b: () -> Int = {
  return a
}

a += 1

print(a)   // 1
print(b()) // 1
```

これを解決するにはクロージャの [capture list](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID544) を使います。 capture list によって状態が共有されなくなります（このような capture list の使い方は @rintaro さんの指摘と、↑を読んで今回初めて知りました）。

```swift
var a: Int = 0

let b: () -> Int = { [a] in
  return a
}

a += 1

print(a)   // 1
print(b()) // 0
```

### ジェネリクスでできないこと

ジェネリクスがあればサブタイピングと似た抽象化ができましたが、ジェネリクスではできないこともあります。

サブタイピングを使えば次のような関数を作れます。

```swift
func useAnimals(_ animals: [Animal]) { ... }
```

しかし、もしジェネリクスで同じような関数を作ったとしましょう。

```swift
func useAnimals<A: Animal>(_ animals: [A]) { ... }
```

このとき、次のように `Cat` と `Dog` が混ざった `Array` を受け取れるのは `[Animal]` の場合だけです。 `[A]` の `A` はあくまで特定の具象型を表すので、 `Cat` と `Dog` を同時に満たすことはできません。

```swift
useAnimals([Cat(), Dog()])
```

### 本当に継承がなくても大丈夫か

継承によって具象型を拡張したい場合はどうすれば良いでしょうか？たとえば、 `UIViewController` は具象クラスですが拡張された様々なサブクラスが存在します。継承することのできない値型ではそのようなことはできません。

しかし、本当に具象型の継承が必要でしょうか？継承によって `class` を拡張することは問題を引き起こしがちなので、基本的には `final class` にして継承は最小限に留めるというのが最近の潮流だと思います。

型の複雑な派生関係はプロトコル間の継承で表し、実装は mix-in 的に protocol extension で挿し込むことで大抵のケースに対応できるのではないでしょうか。逆に、具象型を継承したいと思ったときに見直すと設計がまずかったということも多いと思います。

どんなケースでも不要とまでは言えませんが、多くのケースでは具象型の継承ができなくても困らないのではないでしょうか。

### （余談）HaskellにできてSwiftにできないこと

値型しか使わず、プロトコル型変数も使わない Swift は Haskell に似ていると言いましたが、 Haskell にはできるけど Swift にはできないこともあります。

`Array` と `Optional` は `map` を持っています。次のコードのようにとても似ていることがわかると思います（コードは `rethrows` など話題と関係ない部分を省略し簡略化しています）。

```swift
struct Array<T> {
  func map<U>(_ f: (T) -> U) -> Array<U>
}

enum Optional<T> {
  func map<U>(_ f: (T) -> U) -> Optional<U>
}
```

似たものは抽象化したいですが、 Swift は `Array` と `Optional` を `map` に関して抽象化することができません。 Haskell にはできます。 `map` を持つ型を抽象化したものを `Functor` と呼びますが、任意の `Functor` に対して抽象的にコードを書くことができます。

ただ、これはトピックとしてはおもしろいですが、 Swift では `class` を使おうが `Functor` のような抽象化ができるわけではないので、値型だけを使って Swift でコードを書いてみるというこの発表の主題とはあまり関係がありません。

## まとめ

- 参照型では状態共有問題を避けるためにイミュータブルを使う
- イミュータブルには特有の煩わしさがある
- 値型はイミュータブルな参照型と似ている
- 値型なら状態共有の問題もなく更新も簡単
- コレクションは COW でコピーコストを低減
- サブタイピングを禁止して値型だけで書いた Swift は Haskell に似ている
- サブタイピングがなくてもジェネリクスを使って大抵の抽象化はできる
- 値型と `inout` を組み合わせると楽しい
- 再帰データ構造に関しては値型に煩わしさがある

以上です。これをきっかけに値型でプログラミングすることに興味を持っていただけるとうれしいです。