PureScript by Example の 5.16, 5.17, 5.18 を読む

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

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

## 概要

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

今日は 5.16 から 5 章の終わりまでを読んでいく。ソースコードの例は [purescript-book の chapter5][purescript-book-chapter-5] にある。

※注意事項: 英語と日本語訳では大きな差異がある。`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] 対象バージョン不明

## 前回までのおさらい

この章では代数的データ型 (algebraic data type) とパターンマッチ (pattern matching) および行多相 (row polymorphism) を扱うらしい。

5 章のここまでに出てきたものは次のとおり。あとは例だけのはずなので、これでほぼすべて。

- [Wildcard Patterns (`_`)][language-guide-wildcard-patterns]
- [Literal Patterns (`Number` / `String` / `Char` / `Boolean` ...)][language-guide-literal-patterns]
- [Array Patterns (`[x, y]`)][language-guide-array-patterns]
- [Constructor Patterns (`Foo s`)][language-guide-constructor-patterns]
- [Record Patterns (`{ foo: "Foo", bar: n }`)][language-guide-record-patterns]
- [Nested Patterns (`{ arr: [x, _], take: "firstOfTwo" }`)][language-guide-nested-patterns]
- [Named Patterns (`a@[_, _]`)][language-guide-named-patterns]
- [Guard][language-guide-guards]
- [`case`][language-guide-pattern-matching]
- [部分関数 / `Partial` / `unsafePartial`][language-guide-pattern-matching]
- [`data`][language-guide-tagged-unions]
- [`newtype`][language-guide-newtypes]

Language Guide:

- [Pattern Matching - Language Guide][language-guide-pattern-matching]
- [Tagged Unions - Language Guide][language-guide-tagged-unions]
- [Newtypes - Language Guide][language-guide-newtypes]
- [Top-level declarations - Language Guide][language-guide-top-level-declarations]

## PureScript by Example 5.16

`type` でシノニムを定義している。 `type` keyword とシノニムは 3 章で出てきた。

```
type Picture = Array Shape
```

Language Guide:

- [Type Synonyms - Language Guide][language-guide-type-synonyms]

昨日の `newtype` との違いは、`type` は別名をつけるだけなので互換性があり、 `newtype` は別の型なので互換性がない。

```
> type Int' = Int
> :paste
… let
…   x :: Int'
…   x = 123
…
> x
123

> newtype Int'' = Int'' Int
> :paste
… let
…   y :: Int''
…   y = 123
…
Error found:
in module $PSCI
at  line 3, column 7 - line 3, column 7

  Could not match type

    Int

  with type

    Int''


while checking that type Int
  is at least as general as type Int''
while checking that expression 123
  has type Int''
in value declaration y

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

`Picture` を使って `showPicture` を定義する。

```
showPicture :: Picture -> Array String
showPicture = map showShape
```

手を抜いて purescript-book に書いてあるものを使って psci で試す。

```
> import Data.Picture
> :paste
… showPicture
…   [ Line (Point { x: 0.0, y: 0.0 })
…          (Point { x: 1.0, y: 1.0 })
…   ]
…
["Line [start: (0.0, 0.0), end: (1.0, 1.0)]"]
```

良さそう。

## PureScript by Example 5.17

今度は `data` で `Bounds` を定義する。 `|` が使われていないところを見ると `newtype` でも良さそうだけど……。

```
data Bounds = Bounds
  { top    :: Number
  , left   :: Number
  , bottom :: Number
  , right  :: Number
  }
```

いくつかの `Data.Picture` の関数を使って `bounds` を定義する。`emptyBounds` ・ `\/` および `shapeBounds` は `Data.Picture` の中に定義されているのでそれを見ると良い。

```
bounds :: Picture -> Bounds
bounds = foldl combine emptyBounds
  where
    combine :: Bounds -> Shape -> Bounds
    combine b shape = shapeBounds shape \/ b
```

ふむ。

## まとめ

5 章を終えた。`type` `data` `newtype` が出た。パターンマッチも出た。`{ foo: String | r }` のような行多相も出た。

## 参考

- [PureScript by Example][purescript-by-example]
- [実例による PureScript][purescript-by-example-ja]
- [paf31/purescript-book][paf31/purescript-book]
- [Language Guide][language-guide]
- [Language Guide - Newtypes][language-guide-newtypes]
- [Language Guide - Pattern Matching][language-guide-pattern-matching]
- [Language Guide - Tagged Unions][language-guide-tagged-unions]
- [Language Guide - Top-level declarations][language-guide-top-level-declarations]

## 次回以降の 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) のコードを読む

[paf31/24-days-of-purescript-2016]: https://github.com/paf31/24-days-of-purescript-2016
[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-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-19]: http://qiita.com/bouzuya/items/ade348495b755d57ede0
[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-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-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