PureScript by Example の 6.4 を読む

この記事は [(bouzuya) PureScript Advent Calendar 2016](http://www.adventar.org/calendars/1494) の 20 日目。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録だ。

- ← 19 日目『 [PureScript by Example の 6.1, 6.2, 6.3 を読む - Qiita][2016-12-19] 』
- → 21 日目『 [PureScript by Example の 6.5, 6.6 を読む - Qiita][2016-12-21] 』

## 概要

[PureScript by Example][purescript-by-example] を [PureScript Language Guide][language-guide] や [Pursuit][pursuit] を見ながら進めていく。

今日は 6.4 を読む。ソースコードの例は [purescript-book の exercises/chapter6][purescript-book-chapter-6] にある。

※注意事項: 英語と日本語訳では大きな差異がある。`0.10.x` に対応している英語の側で進める。

- [PureScript by Example][purescript-by-example] 2016-12-05 時点で 0.10.x 向け
- [実例による PureScript][purescript-by-example-ja] 2016-12-05 時点で 0.7 向け
- [PureScript Language Guide][language-guide] 対象バージョン不明

## この章のおさらい

この章では型クラス (type classes) を扱うらしい。

`class` / `instance` キーワードと型クラス `Show` を見た。必要に応じて `::` 演算子で型を指定する方法も見た。

Pursuit:

- [Data.Show - purescript-prelude - Pursuit][pursuit-prelude-show]

[pursuit-prelude-show]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Show#t:Show

## PureScript by Example 6.4

### `Eq`

`Eq` 型クラス。いままで `==` の operator alias 経由で使ってきた `eq` を定義している。

Pursuit:

- [Data.Eq - purescript-prelude - Pursuit][pursuit-prelude-eq]

### `Ord`

`Ord` 型クラス。`compare` を定義している。 `LT` `EQ` `GT` を返す。

Pursuit:

- [Data.Ord - purescript-prelude - Pursuit][pursuit-prelude-ord]

### `Field`

`Field` 型クラス。体 (field) 。検索した感じ抽象代数学に由来する名前っぽいけど、ぼくにはよく分からない。この型クラスとその親 (?) となる型クラスで四則演算を定義しているように見える。参考: [可換体 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%8F%AF%E6%8F%9B%E4%BD%93)

```
class (EuclideanRing a) <= Field a
class (CommutativeRing a) <= EuclideanRing a where -- ...
class (Ring a) <= CommutativeRing a
class (Semiring a) <= Ring a where -- ...
class Semiring a where -- ...
```

体 (field) ・ユークリッド環 (euclidean ring) ・可換環 (commutative ring) ・半環 (semiring) ……だろう。 `Semiring` はゼロイチと加算乗算、 `Ring` は減算、 `EuclideanRing` は剰余などを定義している。

Pursuit:

- [Data.Field - purescript-prelude - Pursuit][pursuit-prelude-field]

### `Semigroup`

`Semigroup` 型クラス。半群 (semigroup) 。また分からない。Pursuit を見る限り結合 (`<>` / `append`) できるもののように見える。[半群 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%8D%8A%E7%BE%A4)

Pursuit:

- [Data.Semigroup - purescript-prelude - Pursuit][pursuit-prelude-semigroup]

### `Monoid`

`purescript-monoid` パッケージの `Monoid` 型クラス。モノイド (monoid) 。またまた分からない。 Pursuit を見る限り `mempty` を提供する `Semigroup` っぽい。 `mempty` は単位元 (?) を表しているのだろうか。空っぽい。 [モノイド - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%8E%E3%82%A4%E3%83%89)

Pursuit:

- [Data.Monoid - purescript-monoid - Pursuit][pursuit-monoid-monoid]

### `Foldable`

`purescript-foldable-traversable` パッケージの `Foldable` 型クラス。 `fold` できるのだろう。 4 章で `fold` は散々出てきた。

```
> foldl append mempty ["Hello", " ", "World"]
"Hello World"

> foldl append mempty [[1, 2, 3], [4, 5], [6]]
[1,2,3,4,5,6]
```

なるほど。`Monoid` の `mempty` と `Semigroup` の `append` を使い、 `Foldable` の `foldl` などでいい感じに処理できると。

あと `Monoid String` / `Monoid (Array Int)` (`Monoid (Array a)`) もあることが分かる。 https://github.com/purescript/purescript-monoid/blob/v2.2.0/src/Data/Monoid.purs#L29-L33 確かにある。

Pursuit:

- [Data.Foldable - purescript-foldable-traversable - Pursuit][pursuit-foldable-traversable-foldable]

### `Functor`

`Functor` 型クラス。関手 (functor) 。`<$>` / `map` を提供する。データ構造に関数を持ち上げる (?) らしい。なるほど、分からない。

```
class Functor f where
  map :: forall a b. (a -> b) -> f a -> f b
```

関数 `a -> b` と Functor `f a` をとって Functor `f b` を返す。ふむ。

```
> import Prelude

> map (\n -> n < 3) [1, 2, 3, 4, 5]
[true, true, false, false, false]

> import Data.Maybe
> import Data.String (length)

> map length (Just "testing")
(Just 7)
```

`Functor Maybe` や `Functor Array` があるようだ。

関数 `(\n -> n < 3)` を `[1, 2, 3, 4, 5]` (`Array Int` / `Functor Array`) に持ち上げて適用し、その結果 `[true, true, false, false, false]` を返す。ふむ。

関数 `length` を `Just "testing"` (`Maybe String` / `Functor Maybe`) に持ち上げて適用し、その結果 `Just 7` を返す。ふむ。

`map` に渡す関数は `Functor` の中身 (?) を取るっぽい。

Pursuit:

- [Data.Functor - purescript-prelude - Pursuit][pursuit-prelude-functor]
- [Data.Maybe - purescript-maybe - Pursuit][pursuit-maybe-maybe]

## まとめ

6.4 だけのはずなのに、すごい勢いで型クラスを紹介されて消耗した。前回の `Show` もそうだけど、どれも基本っぽい感じがする。

## 次回以降の TODO

- PureScript by Example & PureScript Language Guide を読み進める
- `Array` 以外での `do` 記法
- `psc-package`
- [24 Days of PureScript, 2016][paf31/24-days-of-purescript-2016]
- [24 Days of PureScript, 2014](https://gist.github.com/paf31/8e9177b20ee920480fbc)
- 某氏の記事の紹介
- [github.com/purescript](https://github.com/purescript/) のコードを読む
- [github.com/purescript-node](https://github.com/purescript-node) のコードを読む
- [github.com/purescript-contrib](https://github.com/purescript-contrib) のコードを読む


[purescript-by-example]: https://leanpub.com/purescript/read
[purescript-by-example-1]: https://leanpub.com/purescript/read#leanpub-auto-introduction
[purescript-by-example-2]: https://leanpub.com/purescript/read#leanpub-auto-getting-started
[purescript-by-example-3]: https://leanpub.com/purescript/read#leanpub-auto-functions-and-records
[purescript-by-example-4]: https://leanpub.com/purescript/read#leanpub-auto-recursion-maps-and-folds
[purescript-by-example-5]: https://leanpub.com/purescript/read#leanpub-auto-pattern-matching
[purescript-by-example-6]: https://leanpub.com/purescript/read#leanpub-auto-type-classes
[purescript-by-example-7]: https://leanpub.com/purescript/read#leanpub-auto-applicative-validation
[purescript-by-example-8]: https://leanpub.com/purescript/read#leanpub-auto-the-eff-monad
[purescript-by-example-9]: https://leanpub.com/purescript/read#leanpub-auto-canvas-graphics
[purescript-by-example-10]: https://leanpub.com/purescript/read#leanpub-auto-the-foreign-function-interface
[purescript-by-example-11]: https://leanpub.com/purescript/read#leanpub-auto-monadic-adventures
[purescript-by-example-12]: https://leanpub.com/purescript/read#leanpub-auto-callback-hell
[purescript-by-example-13]: https://leanpub.com/purescript/read#leanpub-auto-generative-testing
[purescript-by-example-14]: https://leanpub.com/purescript/read#leanpub-auto-domain-specific-languages

[2016-12-01]: http://qiita.com/bouzuya/items/a5be85ec3e496e5bf436
[2016-12-02]: http://qiita.com/bouzuya/items/806335ea74ead0e33d95
[2016-12-03]: http://qiita.com/bouzuya/items/86cc9aaaddcc1aa790cf
[2016-12-04]: http://qiita.com/bouzuya/items/b2b80c22c50d0c1e739c
[2016-12-05]: http://qiita.com/bouzuya/items/f19ee0b86e9aec3f0afa
[2016-12-06]: http://qiita.com/bouzuya/items/4694ac25f68931115319
[2016-12-07]: http://qiita.com/bouzuya/items/62c6ad30ecba3c68a7a3
[2016-12-08]: http://qiita.com/bouzuya/items/7224535dd053c41748ed
[2016-12-09]: http://qiita.com/bouzuya/items/868eafc19b96619c025a
[2016-12-10]: http://qiita.com/bouzuya/items/1a54ba3702f9818527a5
[2016-12-11]: http://qiita.com/bouzuya/items/ab2bc2d19461203f1ee5
[2016-12-12]: http://qiita.com/bouzuya/items/c42ddb14477716de1dcf
[2016-12-13]: http://qiita.com/bouzuya/items/a49463871a96459d7083
[2016-12-14]: http://qiita.com/bouzuya/items/14ca2a2cd9c0bb01653d
[2016-12-15]: http://qiita.com/bouzuya/items/0511f040381c6c2eba12
[2016-12-16]: http://qiita.com/bouzuya/items/10d8f935c0e5695826c5
[2016-12-17]: http://qiita.com/bouzuya/items/129b2ab8ba3fa89edaf5
[2016-12-18]: http://qiita.com/bouzuya/items/ae7ce46363d0ccdfb03b
[2016-12-19]: http://qiita.com/bouzuya/items/ade348495b755d57ede0
[2016-12-20]: http://qiita.com/bouzuya/items/6e3cc11aa8387b4a5254
[2016-12-21]: http://qiita.com/bouzuya/items/b7e04a015084eb1e8d32

[paf31/24-days-of-purescript-2016]: https://github.com/paf31/24-days-of-purescript-2016
[purescript/purescript]: https://github.com/purescript/purescript
[pursuit]: https://pursuit.purescript.org/
[purescript/documentation]: https://github.com/purescript/documentation
[purescript-by-example-6]: https://leanpub.com/purescript/read#leanpub-auto-type-classes
[purescript-by-example-ja]: http://hiruberuto.bitbucket.org/purescript/
[try-purescript]: http://try.purescript.org/
[language-guide]: https://github.com/purescript/documentation/tree/f48ba1ee7761446e1ae75ee806e51688c1937297/language/

[pursuit-foldable-traversable-foldable]: https://pursuit.purescript.org/packages/purescript-foldable-traversable/2.0.0/docs/Data.Foldable#t:Foldable
[pursuit-maybe-maybe]: https://pursuit.purescript.org/packages/purescript-maybe/2.0.1/docs/Data.Maybe#t:Maybe
[pursuit-monoid-monoid]: https://pursuit.purescript.org/packages/purescript-monoid/2.2.0/docs/Data.Monoid#t:Monoid
[pursuit-prelude-eq]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Eq#t:Eq
[pursuit-prelude-field]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Field#t:Field
[pursuit-prelude-functor]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Functor#t:Functor
[pursuit-prelude-ord]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Ord#t:Ord
[pursuit-prelude-semigroup]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Semigroup#t:Semigroup

[paf31/purescript-book]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/