【Haskell や圏論が出てこない】Scala で型クラスを完全に理解した話

# TL;DR

結論から。

__型クラスはちょっとすごいオーバーロード__ であり __型に対して静的にメソッドを挿入する方法__ です。

この記事は

- Haskell や 圏論等の難しそうな知識・議論なしで型クラス概念を具体的に理解する
- 型クラスが実は単なるすごいオーバーロードで、ちょっとした便利なものだと実感できる
- 型クラスとインターフェイスの違い論争で消耗しなくなる
- 型クラスを知っているとなにがオトクなのかわかる
- Haskell 等の高度な抽象化の恩恵を Java 的な慣れ親しんだシンタックスで書ける Scala は便利でたのしいと感じる

ことを目的としています。

# 対象読者

- 関数型とか型クラスとかモナドとかよく聞くけど全然わからない…でも理解したい気持ちはある
- 型クラスの概念はいろいろ読んでなんとなく分かるけど説明が Haskell ばかりで実感がわかない
- 型クラスがなんなのかはぶっちゃけどうでもいいが、便利なのかどうか、どう便利なのかを知りたい

Scala 自体はわからなくても大丈夫です。

# まえおき

最近またにわかに __型クラス__ が話題になっていました。

モナドや圏論同様、Haskell の神秘じみた概念の一つして定期的に話題になっていて、なんだかすごくてかっこよさそうなんだけれど、そもそも Haskell をよく知らないし、理論色の強い解説が多くなかなかスッキリ消化できない方が多いのではないかと思います。私もその一人です。Haskell とかさっぱりです。

しかし __型クラスが本当に素晴らしいものなら Haskell を使わなくても素晴らしいといえるはず__ ということで、この記事では __Pure Scala__ で型クラスを具体的に理解することを目指します。

# "型クラス" とはなにか

最初に、型クラスそのものではなく、"型クラスという誤解を招きやすい名称" について整理したいと思います。Java や C++ 等にはじまる多くのオブジェクト指向言語では __クラス__ は特別なキーワードとして扱われてきました。そして、それは __型__ と呼ばれる概念とほぼ一対一対応しています。

この慣習がまず __型クラス__ という言葉をわかりづらくしてしまっているように思います。そこで一旦、OOPL での型やクラスという概念を忘れて、本来的な言葉の定義を考え直してみます。

__型__ は

> [けい【型】［漢字項目］の意味 - goo国語辞書 - goo辞書](https://dictionary.goo.ne.jp/jn/65935/meaning/m0u/)
> 1. 同形のものをいくつも作るとき元になるもの。いがた。「原型・紙型・母型」
> 2. 基準となる形。タイプ。「型式／定型・典型・模型・類型」

となっており、鋳型等、同じ形をしたものを作るもの・その枠といった意味です。もうちょっとプログラム的に言えば __一定の決まったデータ構造の約束__ と言えそうです。

一方 __クラス__ は

> [Weblio - class](http://ejje.weblio.jp/content/class)
> (共通の性質を有する)部類、種類、(学校の)クラス、学級、組、(クラスの)授業(時間)、(編物教室などの)講習、クラスの生徒たち、同期卒業生、同年兵

となっており、__共通の性質をもった集まり__ であると言えそうです。

つまり、型クラスとは型のクラス = 似たような性質を持った型の集まり、というふうに読み取ることができ、これは実際型クラスをよく説明する表現になっています。

__型クラス = 共通の性質を持った型の集まり__

というわけで前置きが長くなりましたが、言葉の意味を明らめたところで実際に型クラスとはどういうもので、型クラスが一体何を実現してくれるのか見ていきたいと思います。

# 型クラスを見て体験する

まずは、型クラスがどんなコードの見た目をしていて何ができるのかを確認してみます。Scala のコードですが、Scala を知らない人でも雰囲気がつかめれば大丈夫ですので、細かいシンタックスは気にせず見てみてください。

まずは、以下のような仕様の実装について考えます。

`sum` という List を受け取ってその合計を返す関数を定義したいとします。この際、`sum` が引数に受け取る型は、ただ 1 つの `List[Int]` などではなく、__合計という概念が適用できる型__ を幅広く受け取れるようにしたいでしょう。このように多くの型を受け取れることを「多相」と呼びます。

言い換えると、合計という概念が適用できるある型 `A` を要素に持つ `List[A]` を引数に取る多相なメソッド `sum` を作りたい、です。ここで、型 `A` は拡張できない or 拡張したくない既存の型とします。

ここでいったん合計という概念の詳細は考えずに、まずは `Int` と `String` の2つに対応してみましょう。自然に実装できるでしょうか？

## sum メソッドのナイーブな実装

```scala
def sum(xs: List[Int]): Int = xs match {
  case Nil => 0
  case head :: tail => head + sum(tail)
}

def sum(xs: List[String]): String = xs match {
  case Nil => ""
  case head :: tail => head + sum(tail)
}

sum(List(1, 2, 3))        // => 6
sum(List("a", "b", "c"))  // => "abc"
sum(List(true, false))    // Kaboom! Can't compile
```

型クラスがでてくるかと思いきや拍子抜けしたかもしれませんが、実はオーバーロード / アドホック多相で上記の仕様を満たすことができます。簡単にコードの説明をすると

1. 引数の List を `match` (`switch` のようなものです) で `Nil` と それ以外で場合分け
1. `Nil` だったら受け付ける型のデフォルト値を返す
1. List が要素を持つならその先頭の値 `head` と List の残りの要素 `tail` の総和を足す

ということをやっています。

オーバーロードの引数の型として、合計という概念が適用できる型を列挙し、それぞれの実装を与えることで自然に型にそった処理を実現できています。

この実装によって明らかになった性質がいくつかあります。

- 合計という概念が適用できる型を明に列挙することで、それ以外の型で利用しようとした場合は静的にコンパイルエラーにすることができる
- オーバーロードの制約となる型は既存の型であり、既存の型を修正したり拡張したりせずに新たに振る舞いを追加できる
- 合計というセマンティクスは共通だが、型ごとに実装は異なる

同時に、この実装にはいくつか問題を指摘することができるかと思います。

まず、`sum(xs: List[Int]): Int` と `sum(xs: List[String]): String` でほとんど実装が重複してしまっています。DRY じゃないですね。

また、今の `sum` は `Int` と `String` のみにしか対応できていません。もちろんこれら以外の合計が適用できる型には対応できていないですし、仮に多くの型のオーバーロードを用意したとしても、 `sum` の利用者が追加する独自の型に対応することはできません。つまり、拡張性・再利用性が無い状態になってしまっています。

これらの問題を解決して拡張性を得るためには、__合計という概念が適用できる型__ をきちんと取り扱う必要がありそうです。

そこで少し今の `sum` の実装を見直してみます。問題点として挙げた __実装の重複__ という観点から、`Int` と `String` で共通な部分と異なる部分を抽出してみます。

共通な部分は

- リストの要素の _たぐり方_
- リストが `Nil` だったときには、引数の型のデフォルト値を返す
- 引数の型同士の加法を利用した合計の実装

異なる部分は

- `Int`、`String` それぞれのデフォルト値
- `Int`、`String` それぞれの加法の具体的な実装

です。

ここから List に内包される __合計という概念が適用できる型__ の条件として __加算が定義できる型__ であることが言えそうです。このような加算が定義できる型を `Addable` な型と呼ぶことにしましょう。そうすると、`sum` メソッドは __`Addable` な性質を定義できる型の集合__ を要素として持つ List を受け入れたいと言えます。

それができる __すごいオーバーロード__ が __型クラス__ ということになります。

早速上記の仕様の型クラスでの実装をみてみましょう。

## sum メソッドの型クラスでの実装

```scala
def sum[A](xs: List[A])(implicit addable: Addable[A]): A = xs match {
  case Nil => addable.unit
  case head :: tail => addable.add(head, sum(tail))
}

trait Addable[A] {
  val unit: A
  def add(x: A, y: A): A
}

implicit object AddableInt extends Addable[Int] {
  override val unit: Int = 0
  override def add(x: Int, y: Int): Int = x + y
}

implicit object AddableString extends Addable[String] {
  override val unit: String = ""
  override def add(x: String, y: String): String = x + y
}

sum(List(1, 2, 3))        // => 6
sum(List("a", "b", "c"))  // => "abc"
sum(List(true, false))    // Kaboom! Can't compile
```

Scala を知らない方は `trait` や `object`、`implicit` 等の見慣れないキーワードが出てきてちょっと混乱するかもしれませんが、落ち着いてオーバーロードの実装と見比べてみると概形が見えてくるのではないかと思います。Scala の説明もしながら、順を追って見ていきます。

まず `sum` メソッドの実装を 1 ヶ所に集中するために、型パラメータ `A` を導入しました。

```scala
def sum[A](xs: List[A])(implicit addable: Addable[A]): A = xs match {
  case Nil => addable.unit
  case head :: tail => addable.add(head, sum(tail))
}
```

早速いくつか Scala 特有の記法があるため簡単に補足します。 `def` はメソッドを定義するキーワードで、`def hoge(): Piyo` のような形で使います。最後の `Piyo` が戻り値の型です。Scala ではメソッドのパラメータを複数の _パラメータリスト_ として記述することができます。なので `()` が 2 つありますが、単に引数が並んでいるだけだと思ってもらって大丈夫です[^1]。2 個目のパラメータリストにあるキーワード `implicit` は型クラスを実現する重要な機能で、__オーバーロードと同様に__ 型情報を元にコンパイラが暗黙的に挿入すべき値を解決します。つまり、`Addable[A]` の型を見て自動的にその型に適合した `addable` が挿入されます。型によって実際に呼び出すメソッドが決まるオーバーロードそっくりですね。

[^1]: カリー化などで調べると説明があるかと思います

ここで、あらためて `sum` の型 `A` に関する実装について、共通の部分と異なる部分を再確認してみます。

共通な部分は

- リストの要素の _たぐり方_
- リストが `Nil` だったときには型 `A` のデフォルト値を返す
- 型 `A` 同士の加法を利用した合計の実装

異なる部分は

- 型 `A` のデフォルト値
- 型 `A` の加法の実装

です。

`sum[A](xs: List[A])(implicit addable: Addable[A]): A` メソッドには共通の List のたぐり方が実装されています。対して型 `A` に共通の振る舞いが `sum` の次の `Addable[A]` に定義されています。

```scala
trait Addable[A] {
  val unit: A
  def add(x: A, y: A): A
}
```

`trait` というのは実装の持てる interface のようなものです。ここには見ての通り、ある型 `A` のデフォルト値が `unit` という変数で表され、加法が `add(x: A, y: A): A` というシグネチャで宣言されています。ここで宣言した `Addable` = 加算が定義できる 性質が、合計という概念を適用できる型の条件でした。

さて、ここまでで `sum` に共通な要素を記述することができました。ここからはオーバーロード同様に、合計という概念が適用できる型それぞれについて `Addable` の実装を与えていきましょう。

```scala
implicit object AddableInt extends Addable[Int] {
  override val unit: Int = 0
  override def add(x: Int, y: Int): Int = x + y
}

implicit object AddableString extends Addable[String] {
  override val unit: String = ""
  override def add(x: String, y: String): String = x + y
}
```

またしても `implicit` キーワードが出てきましたが、ここまでくればもう分かる通り、この `implicit` は `sum` メソッドの引数における `implicit` とこの実装を紐付けるための目印になっています。オーバーロードでは、共通のメソッド名で異なる引数型であれば自動的にオーバーロードであることがコンパイラに伝わりますが、`implicit` を利用する場合にはコンパイラに明示的に教えてあげる必要があります。

`object` というのは __シングルトンオブジェクト__ のことで、Scala では言語組み込みの仕様になっています。`object` は定義と同時に型の名前でアクセスできる static なクラスのようなものだと思ってください。このシングルトンオブジェクトで、`Int`、`String` それぞれの型に固有の処理を実装として与えています。

さて、一通り眺めてきましたが、いまここを読んでいる方は上記のシングルトンオブジェクトの実装がオーバーロードのように見えてきているのではないでしょうか？もう一度、実際に並べて比べてみます。

## オーバーロードと型クラスの比較

### オーバーロード

```scala
def sum(xs: List[Int]): Int = xs match {
  case Nil => 0
  case head :: tail => head + sum(tail)
}

def sum(xs: List[String]): String = xs match {
  case Nil => ""
  case head :: tail => head + sum(tail)
}
```

### 型クラス

```scala
def sum[A](xs: List[A])(implicit addable: Addable[A]): A = xs match {
  case Nil => addable.unit
  case head :: tail => addable.add(head, sum(tail))
}

trait Addable[A] {
  val unit: A
  def add(x: A, y: A): A
}

implicit object AddableInt extends Addable[Int] {
  override val unit: Int = 0
  override def add(x: Int, y: Int): Int = x + y
}

implicit object AddableString extends Addable[String] {
  override val unit: String = ""
  override def add(x: String, y: String): String = x + y
}
```

型クラスのほうがちょっと実装が長くなってしまっていますが、オーバーロードの実装で問題の一つだった重複した実装が、ジェネリックな `sum` メソッドによって一本化できています。

さらに、オーバーロードのもう一つの問題点だった拡張性についても、型クラスでは改善しています。今、合計という概念が適用できる型として `Double` を発見し、`Double` についても `sum` メソッドが利用したくなったとします。この時、`sum` の実装については手を加えずに、`sum` を拡張することができます。

```scala
implicit object AddableDouble extends Addable[Double] {
  override val unit: Double = 0.0
  override def add(x: Double, y: Double): Double = x + y
}

sum(List(1.0, 2.0, 3.0)) // => 6.0
```

さらにさらに、自作の有理数を扱う `Rational` クラスをつくったとしましょう。`Rational` クラスには `Rational` 同士を加算する `add` メソッドが定義されているとします。この時、`sum` の実装については手を加えずに

```scala
implicit object AddableRational extends Addable[Rational] {
  override val unit: Rational = Rational(0, 1)
  override def add(x: Rational, y: Rational): Rational = x.add(y)
}

sum(List(Rational(1, 2), Rational(1, 3), Rational(1, 4))) // => 13/12
```

_気持ちよくなってきた。_

というわけで型クラスを見てきましたが、もう型クラスについては怖くなくて、オーバーロードのようにすっかり手に馴染むようになってきたのではないでしょうか？

# 型クラスとは

ここで、型クラスの性質をまとめてみます。

- あるジェネリックなメソッドが __受け入れられる型の集まり__ を型クラスの実装として明に列挙することで、それ以外の型では静的にコンパイルエラーにすることができる(__型クラス制約__)
- 型クラス制約を与える型は既存の型でよく、既存の型を修正したり拡張したりせずに新たに振る舞いを追加できる
- 型クラス制約を受ける型の振る舞いは共通だが、型ごとに実装は異なる
- 既存の型クラスに適合させたい型が増えた場合には、その型クラスの実装を提供するだけでよい(たとえば `sum` メソッドに手を入れる必要がない)

これは前述のオーバーロードの満たす性質と近く、より抽象的な / 拡張に対して開いたものになっています。特に、ライブラリ実装者が型クラスを用いることで、利用者はライブラリによってなされた実装に対して手を加えることなくそれを拡張することができます。

実際、今回扱った `sum` メソッドでは `Double` や `Rational` といったすでに存在する一般の型について、`sum` メソッドだけでなく型そのものについても直接変更を加えず、後付で `Addable` な性質を実装することができました。

これらが、型クラスが便利で、コードをより抽象的で整理されたものにしてくれるといわれる所以ではないかと思います。

そもそも実は、型クラスという仕組み自体が _この記事で名前の出せないあの言語_ で一般性の高いアドホック多相 / オーバーロードを実現するための仕組みとして導入されました。これについては[別記事](http://qiita.com/Biacco/items/083f05d5d1d87730f7db)で扱っていますが、__型クラスがちょっとすごいオーバーロード__ というのは言い過ぎではないはずです。

型クラスがわかってきたところで、よくある __型クラスとインターフェースの違い__ について考えてみます。

# 型クラスとインターフェースとの違い

型クラスは、ある型に対するメソッドの存在を約束するという点でインターフェースと似ており、よく比較されています。実際、Scala の型クラスの実装でも `trait Addable[A]` のようなかたちで、`trait` による抽象化が行われていました。

では、インターフェース(トレイト)と型クラスではなにが違うのか、`sum` や `Addable` の実装についてインターフェースを用いたサブタイプ多相による実装を考えてみます。

## `Addable[A]` インターフェースを継承したクラスの値を扱う `sum`

```scala
trait Addable[A] {
  val value: A
  def add(x: Addable[A]): Addable[A]
}

class AddableInt(override val value: Int) extends Addable[Int] {
  override def add(x: Addable[Int]): Addable[Int] = new AddableInt(value + x.value)
}

def sum[T](xs: List[Addable[T]]): Addable[T] = xs match {
  case Nil => null
  case head :: Nil => head
  case head :: tail => head.add(sum(tail))
}

sum(List(1, 2, 3).map{ new AddableInt(_) }).value // => 6
```

渡された List が空の場合はデフォルト値が取得できないので `null` を返してしまったり、そういう設計のため `add` や `sum` の引数・戻り型が `A` でなく `Addable[A]` になってしまっていたり、 `List[Int]` を包み直したりなかなか難儀な感じになってしまいましたが、ほぼ似たような実装ができています。が、型に紐づく処理を挿入するためだけにすべての値をインターフェースに適合した型にラップしており無駄が多いし素直じゃないですね。

Java だとこういうときは __ストラテジーパターン__ が自然かもしれません。

## `AddStrategy[A]` インターフェースをストラテジーとする `sum`

```scala
def sum[A](xs: List[A])(addStrategy: AddStrategy[A]): A = xs match {
  case Nil => addStrategy.unit
  case head :: tail => addStrategy.add(head, sum(tail))
}

trait AddStrategy[A] {
  val unit: A
  def add(x: A, y: A): A
}

object AddStrategyInt extends AddStrategy[Int] {
  override val unit: Int = 0
  override def add(x: Int, y: Int): Int = x + y
}

sum(List(1, 2, 3))(AddStrategyInt) // => 6
```

もうおわかりだと思いますが、これはほぼ完全に型クラスによる実装と同じです。`implicit` による自動挿入だけがない状態になっています。

## インターフェース・サブタイピング、Scala でできないこと

インターフェースの実装でできていなこと、ひいては Scala でできないことは、結局のところジェネリックなメソッドの型パラメータ `A` からスタティックなメソッドが呼べないことです。(既存の型 `A` に対して `unit` 等の拡張ができないというのもありますが...[^2])

[^2]: `implicit` を用いた暗黙の型変換(Pimp my liblary パターンとも呼ばれるらしい)で既存型に対して拡張は可能ですが、わかりづらさ等の理由で最近はあまり推奨されていないようです。

```scala
// これはできない
def sum[A](xs: List[A]): A = xs match {
  case Nil => A.unit
  case head :: tail => A.add(head, sum(tail))
}
```

Scala は pure な OOP を標榜しており、__method は常にそれの所属するインスタンスを必要とします__。Scala に `static` キーワードがなく、実質的な `static` として機能するのがシングルトンオブジェクトである `object` であることからも、Scala がメソッドの呼び出しに常にインスタンスを必要とするオブジェクト指向を目指していることがわかります。

そこで、__型に紐付いた static なメソッドを呼び出すためのプレースホルダ__ が `implicit object` だったわけです。上記の `A` と下記の `addable: Addable[A]` が対応していることがわかるかと思います。

```scala
// 型クラスによる A の addable への置き換え
def sum[A](xs: List[A])(implicit addable: Addable[A]): A = xs match {
  case Nil => addable.unit
  case head :: tail => addable.add(head, sum(tail))
}
```

## 型クラスとインターフェースの違いまとめ

まとめると、インターフェースと型クラスは似ているようですが、__そもそも目的の違うもので比べるものではない__ ということです。

インターフェースはそれを継承したものにその __実装を強制する仕組み__ です。この仕組自体は型クラスの実装でも用いられていました。

一方型クラスは、その約束された実装を __型情報に基づいて自動的に挿入する__ 仕組みでした。型クラスを実現するためには挿入する実装を約束するために、__インターフェースが必要__ でした。

型クラスとインターフェースは似たような性質を見かけ上持っているため比較されたりしていますが、そもそも対置して比較できるものではなく、むしろ型クラスがインターフェースに依存している、協調的な関係になっています。

インターフェースでの実装でも示した通り、インターフェース自体は様々な使い方ができ、ポイントだったのは __型に対する実装をデータ型と同じ場所に置くか、違う場所に置いて適宜挿入するか__ ということでした。

この、型に対する実装をインターフェースで約束して、データ型と違う場所に置いて自動的に挿入してくれる仕組みこそが型クラスの正体でした。

その点でも、型クラスが __アドホック多相・オーバーロードのための仕組み = 型情報に基づいて自動的に実装を挿入する仕組み__ であるということが納得できるかと思います。

長々とやってきましたが、最後に型クラスを知っているとなにが嬉しいかを紹介して終わりにしようと思います。

### おまけ - なぜ型クラスとインターフェースが混同されてしまったか

おそらく、型クラスの原点である Haskell において、型クラスがインターフェースの仕組みを暗黙に内包していることが原因ではないかと思います。

前述の通り、型クラスは仕組み上、実装の約束をするためのインターフェースを必ず必要とします。しかし、Haskell はオブジェクト指向な言語ではないため、そもそもインターフェースというオブジェクト指向の仕組みを持ちませんでした。継承とかないですからね。

そのため、型クラス導入の際に、型クラスを実現するキーワード `class` が実質的にインターフェースの部分を担うことになりました。

このことが型クラスとインターフェースが混同されて議論される原因の一端ではないかと思っています。おまけおわり。

# 型クラスを理解すると嬉しいこと

型クラスを理解しているとなにが嬉しいでしょうか。個人的には、ライブラリやフレームワーク等の抽象的なコードを書く側でない限り __型クラスによる実装を書く機会はめったにない__ と思います。

では、型クラスの知識はムダなのかというとそんなことはありません。ライブラリを作成する際はもちろん、 __ライブラリを利用する・コードを読む際にとても役立ちます__。

Scala のライブラリでは、標準ライブラリも含めて型クラスによる実装が様々なところに見つけられます。Scala のコレクションのように _高階型_ を伴う実装や Json パーサー等の型によって異なる実装を挿入したい場合において型クラスは非常によく用いられているため、それらを利用する際に型クラスの知識があると __シグネチャから実装の意図が容易に汲み取れます__。

たとえば、Scala の Json パーサーの 1 つである `play-json` の `Json.fromJson` メソッドのシグネチャを見てみます。

```scala
def fromJson[T](json: JsValue)(implicit fjs: Reads[T]): JsResult[T]
```

型クラスの知識があると、ドキュメントがなくても `Reads[T]` 型の意図するところ、求められる実装がこのシグネチャからわかるのではないでしょうか？実際にこのメソッドを使うコードを示します。

```scala
case class Cat(name: String, age: Int)
object Cat {
  implicit val jsonReads: Reads[Cat] = Json.reads[Cat] // 型クラスの実装の提供
}

val json = Json.parse(
  """{
    "name" : "Tama",
    "age" : 4
  }"""
)

val cat = Json.fromJson[Cat](json)  // ここに implicit に jsonReads が渡されている
// --> val cat = Json.fromJson[Cat](json)(jsonReads) と同じ
```

`Json.reads[Cat]` は実はマクロで、`Cat` 型の実装から Json を `Cat` 型にパースする `Reads[Cat]` のインスタンスを生成してくれます。`Cat` 型に特殊化した実装を型クラスのインスタンスとして提供しているわけですね。

このように、ユーザー側で定義した型について、型クラスを利用することで型固有の処理をあとから利用者が差し込めるようになっています。型の定義場所にその型のパーサを `implicit` に提供することで、実際に Json をパースするところでは型に固有のパーサーを意識しなくて済むようになっています。

というわけで、型クラスを知っていると利用者としてもメリットが有ることがわかったかと思います。自分で積極的に使わなくても、コードを読む際に重宝するという点で、Scala におけるデザインパターンの一つとして捉えても差し支えないでしょう。

どうでしょうか？型クラスがどんなものか具体的に理解できたでしょうか。

本当に型クラスの指すものがこれであっているのか気になる、型クラスの定義自体を知りたい、という場合は[型クラスの原点 How to make ad-hoc polymorphism less ad hoc を読んだ話](http://qiita.com/Biacco/items/083f05d5d1d87730f7db)も参照してみてください。

型クラス完全に理解した。

# 補足1 - `sum` メソッドと `fold`

今回の `sum` メソッドの実装は、デフォルト値と加算という処理を使って List の値を走査して単一の戻り値を作っていました。これについて、関数型と呼ばれる言語を扱ったことがある人は `fold` が思いついたのではないかと思います。まさに `fold` は `sum` のようなリスト構造をたぐる処理の一般的表現になっています(より一般性があるのは `foldLeft` / `foldRight` ですがここでは簡単のため `fold` とします)。

```scala
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
```

Scala のコレクションの根幹になっている [GenTraversableOnce[+A]](https://github.com/scala/scala/blob/v2.12.2/src/library/scala/collection/GenTraversableOnce.scala#L164) にこの定義がありますが、これはデフォルト値 `z` と、 `A1` 型の 2 つの値を取って `A1` 型の値を返す関数オブジェクトを引数にとっており、それぞれが `Addable` の `unit` と `add` に相当してることがわかると思います。`fold` を使って `sum` と同様の実装を与えてみます。

```scala
List(1, 2, 3).fold(0){ (acc, i) => acc + i }
List(1, 2, 3).fold(0){_ + _}
List(1, 2, 3).fold(AddableInt.unit){ AddableInt.add }
```

2 行目は省略記法で、1 行目と意味するところは同じです。`fold` では型クラスやオーバーロードよりさらに柔軟に、利用するその場で処理を記述できるようになっています。これは関数を一級市民として扱うことで、__関数型という型__ の宣言ができるようになり、それがインターフェースとして機能しているわかりやすい例だと思います。3 行目はわかりやすさのため、という名の悪ふざけです。

`fold` に対して型クラスが優れている点は、型に応じて自動的に処理が挿入される点ですが、概ねの場合はこういった関数オブジェクトを渡すことでなんとかなるのではないかと実は思っています。実際、ここで挿入される関数オブジェクトは `List(1, 2, 3)` から推論される型 `Int` により `(Int, Int) => Int` であることが静的に解決されるので、型的に安全になっています。

# 補足2 - Context bound な型クラス制約の書き方

Scala の型クラスについてはもうちょっとオシャレに書く方法が用意されています。Context bound というやつです。

```scala
def sum[A: Addable](xs: List[A]): A = xs match {
  case Nil => implicitly[Addable[A]].unit
  case head :: tail => implicitly[Addable[A]].add(head, sum(tail))
}
```

引数として渡されていた `(implicit addable: Addable[A])` をなくして、`implicitly[Addable[A]]` というかたちで `Addable[A]` の実態を参照できるようになりました。おしゃれではあるのですが、見た目が直感的じゃないので賛否両論かもしれません。

# 参考

[Martin Odersky. _Poor man's Type Classes_](http://lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf)
[Philip Wadler. _How to make ad-hoc polymorphism less ad hoc_](http://homepages.inf.ed.ac.uk/wadler/topics/type-classes.html#class)
[JSON automated mapping](https://www.playframework.com/documentation/2.6.x/ScalaJsonAutomated)