PureScript by Example の 6.5, 6.6 を読む

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

- ← 20 日目『 [PureScript by Example の 6.4 を読む - Qiita][2016-12-20] 』
- → 21 日目『 [PureScript by Example の 6.7, 6.8, 6.9, 6.10 を読む - Qiita][2016-12-21] 』

## 概要

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

今日は 6.5, 6.6 を読む。ソースコードの例は [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` / `Eq` / `Ord` / `Field` / `Semigroup` / `Monoid` / `Foldable` / `Functor` を見た。必要に応じて `::` 演算子で型を指定する方法も見た。

Pursuit:

- [Data.Show - purescript-prelude - Pursuit][pursuit-prelude-show]
- [Data.Eq - purescript-prelude - Pursuit][pursuit-prelude-eq]
- [Data.Ord - purescript-prelude - Pursuit][pursuit-prelude-ord]
- [Data.Field - purescript-prelude - Pursuit][pursuit-prelude-field]
- [Data.Semigroup - purescript-prelude - Pursuit][pursuit-prelude-semigroup]
- [Data.Monoid - purescript-monoid - Pursuit][pursuit-monoid-monoid]
- [Data.Foldable - purescript-foldable-traversable - Pursuit][pursuit-foldable-traversable-foldable]
- [Data.Functor - purescript-prelude - Pursuit][pursuit-prelude-functor]
- [Data.Maybe - purescript-maybe - Pursuit][pursuit-maybe-maybe]

## PureScript by Example 6.5

型注釈 (Type Annotations) 。関数の型に制約をつけることができる。 `=>` 。

```
threeAreEqual :: forall a. Eq a => a -> a -> a -> Boolean
threeAreEqual a1 a2 a3 = a1 == a2 && a2 == a3

showCompare :: forall a. (Ord a, Show a) => a -> a -> String
showCompare a1 a2 | a1 < a2 =
  show a1 <> " is less than " <> show a2
showCompare a1 a2 | a1 > a2 =
  show a1 <> " is greater than " <> show a2
showCompare a1 a2 =
  show a1 <> " is equal to " <> show a2
```

`a` の `Eq` インスタンスが存在する場合だけ引数に取ることができる……みたいな感じ。

```
> import Prelude ((+))
> :t \x -> x + x
forall t2. (Semiring t2) => t2 -> t2
```

ある程度、推論もするらしい。

## PureScript by Example 6.6

インスタンスの重複はエラーになる。

PureScript by Example とは違う例を試そうとしたら orphan instance というエラーを出してしまった。参考: [Orphan instances - maoeのブログ](http://maoe.hatenadiary.jp/entry/20100902/1283358286) 。 `data` 定義とは別のところで `instance` を定義することを許していないのか。

```
> import Prelude
> :paste
… instance showBoolean :: Show Boolean where
…   show true = "true"
…   show false = "false"
…
Error found:
in module $PSCI

  Type class instance showBoolean for

    Data.Show.Show Boolean

  is an orphan instance.
  An orphan instance is an instance which is defined in neither the class module nor the data type module.
  Consider moving the instance, if possible, or using a newtype wrapper.

in type class instance

  Data.Show.Show Boolean


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

どちらにせよ `newtype` で別の型にしてから、それへの `instance` にしろ、ということらしい。

## まとめ

`=>` はざっと眺めるだけでも出てくるし、雰囲気で読めるので良し。インスタンスの重複は許さないことでシンプルになるんだろうな、きっと。

明日で年内の業務が終わる (日記) 。

## 次回以降の 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/92d21ee3bbfde3399888

[pursuit-prelude-show]: https://pursuit.purescript.org/packages/purescript-prelude/2.1.0/docs/Data.Show#t:Show
[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/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/
[paf31/purescript-book]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/
[purescript-book-chapter-6]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/exercises/chapter6