PureScript by Example の 6.1, 6.2, 6.3 を読む

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

- ← 18 日目『 [PureScript by Example の 5.15 を読む - Qiita][2016-12-18] 』
- → 20 日目『 [PureScript by Example の 6.4 を読む - Qiita][2016-12-20] 』

## 概要

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

今日は 6.1, 6.2, 6.3 を読む。ソースコードの例は [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] 対象バージョン不明

## PureScript by Example 6.1

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

## PureScript by Example 6.2

この章のための package は次のとおり。ソースコードは上記のは [purescript-book の exercises/chapter6][purescript-book-chapter-6] にある。

- `purescript-maybe`
- `purescript-tuples`
- `purescript-either`
- `purescript-strings`
- `purescript-functions`

名前からはとても基本っぽい package が並んでいるように思える。

## PureScript by Example 6.3

型クラス `Show` とそのインスタンス `Show Boolean` が挙げられている。実際のコードは `purescript-prelude` パッケージの https://github.com/purescript/purescript-prelude/blob/970637279c95bf4a4c371aaac921cc42d5c6137d/src/Data/Show.purs#L9-L14 。

```
class Show a where
  show :: a -> String

instance showBoolean :: Show Boolean where
  show true = "true"
  show false = "false"
```

`Show` は [2016-12-04][] 以降に何度も出てきた `show` を適用できることを表す型クラスだ。[2016-12-07][] でも触れたとおり `Show` インスタンスは `show` を適用できる。 `show :: a -> String` から分かるとおり、任意の型から文字列に変換する関数だ。 JavaScript で言うところの `Object.prototype.toString()` のようなものだ。

`class` / `instance` は初出だ。型クラスを定義するキーワードと、インスタンスを定義するキーワードだ。

型クラス・インスタンスは Java などにおけるクラス・インスタンスとは違う点に注意。ぼくは型におけるクラスとそのインスタンスとしての型……のイメージで見ている。型クラスは Java で言うとインタフェースが近いように思う。

`Data.Tuple` や `Data.Either` に対しての `show` を試す例が続く。注目したいのは `show (Left 10)` におけるエラーだろうか。

```
> import Prelude
> import Data.Either
> show (Left 10)
Error found:
in module $PSCI

  The inferred type

    forall t2. (Show t2) => String

  has type variables which are not mentioned in the body of the type. Consider adding a type annotation.

in value declaration it

See https://github.com/purescript/purescript/wiki/Error-Code-AmbiguousTypeVariables for more information,
or to contribute content related to this error.
```

これは `Left 10` から型を推論できないことによるもの。 `Either a b` のうち `a` は `Int` だと分かるが `b` が分からない。

こういう場合には `::` 演算子を使う。

```
> show (Left 10 :: Either Int String)
"(Left 10)"
```

関数などが `Show` インスタンスでないことにも触れられている。

```
> import Prelude
> show (\n -> n + 1)
Error found:
in module $PSCI
at  line 1, column 1 - line 1, column 18

  No type class instance was found for

    Data.Show.Show (Int -> Int)


while inferring the type of show (\n ->
                                    (add n) 1
                                 )
while applying a function show
  of type forall a. (Show a) => a -> String
  to argument \n ->
                (add n) 1
in value declaration it

See https://github.com/purescript/purescript/wiki/Error-Code-NoInstanceFound for more information,
or to contribute content related to this error.
```

なるほど。

## まとめ

とりあえず今日は `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) のコードを読む

[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

[paf31/24-days-of-purescript-2016]: https://github.com/paf31/24-days-of-purescript-2016
[purescript-by-example]: https://leanpub.com/purescript/read
[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/


[language-guide-pattern-matching]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#pattern-matching
[language-guide-wildcard-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#wildcard-patterns
[language-guide-literal-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#literal-patterns
[language-guide-variable-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#variable-patterns
[language-guide-array-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#array-patterns
[language-guide-constructor-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#constructor-patterns
[language-guide-record-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#record-patterns
[language-guide-nested-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#nested-patterns
[language-guide-named-patterns]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#named-patterns
[language-guide-guards]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Pattern-Matching.md#guards

[language-guide-newtypes]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Types.md#newtypes
[language-guide-tagged-unions]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Types.md#tagged-unions
[language-guide-top-level-declarations]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Syntax.md#top-level-declarations
[language-guide-type-synonyms]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Types.md#type-synonyms
[paf31/purescript-book]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/
[purescript-book-chapter-5]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/exercises/chapter5