PureScript by Example の 5.12, 5.13, 5.14 を読む

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

- ← 15 日目『 [PureScript by Example の 5.10, 1.11 を読む - Qiita][2016-12-15] 』
- → 17 日目『 [PureScript by Example の 5.15 を読む - Qiita][2016-12-17] 』

## 概要

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

今日は 5.12 から読んでいく。ソースコードの例は [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) を扱うらしい。

`Number` `String` `Char` `Boolean` `Array` `Record` のパターンマッチを見た。またガード・パターンマッチのネスト・ `@` で名前付け・ `case` 式・部分関数と `unsafePartial` を見た。

Language Guide:

- [Top-level declarations][language-guide-top-level-declarations]

## PureScript by Example 5.12

代数的データ型 (ADT: Algebraic Data Types) 。 `Shape` での例が挙げられている。

```
data Point = Point
  { x :: Number
  , y :: Number
  }

data Shape
  = Circle Point Number
  | Rectangle Point Number Number
  | Line Point Point
  | Text Point String
```

`Int` や `String` だけでなく `Array` や `Record` や ADT も含むことができる。型構築子 (type constructor) とデータ構築子 (data constructor) の違いを理解すべき。なるほど。

`data 型構築子 = データ構築子 [| データ構築子 [| ...]]` という形式で定義するようだ。

また Language Guide では Tagged Unions として書かれている。ふむ。

Language Guide:

[Tagged Unions - Language Guide][language-guide-tagged-unions]


他の例として `Maybe` と `List` が挙げられている。それぞれ `purescript-maybe` パッケージと `purescript-lists` パッケージから来ている。

```
data Maybe a = Nothing | Just a
data List a = Nil | Cons a (List a)
```

`Maybe` は値がない (`Nothing`) 、または (`|`) ただの `a` (`Just a`) を表している。`Nothing` / `Just` というデータ構築子がある。 `a` は任意の型だろう。

`List` は空のリスト (`Nil`) 、または (`|`) 要素 `a` と残りのリスト (`List a`) から構成 (`Cons`) されることを表している。再帰的だ。 `Nil` / `Cons` というデータ構築子がある。 `a` は任意の型だろう。

## PureScript by Example 5.13

使ってみる。

```
exampleLine :: Shape
exampleLine = Line p1 p2
  where
    p1 :: Point
    p1 = Point { x: 0.0, y: 0.0 }

    p2 :: Point
    p2 = Point { x: 100.0, y: 50.0 }
```

`Line` を使って `Shape` を構築している。 `Line` のために `Point` をふたつ構築している。特に難しいことはない。

次の例。

```
showPoint :: Point -> String
showPoint (Point { x, y }) =
  "(" <> show x <> ", " <> show y <> ")"

showShape :: Shape -> String
showShape (Circle c r) =
  "Circle [center: " <> showPoint c <> ", radius: " <> show r <> "]"
showShape (Rectangle c w h) =
  "Rectangle [center: " <> showPoint c <> ", width: " <> show w <> ", height: " <> show h <> "]"
showShape (Line start end) =
  "Line [start: " <> showPoint start <> ", end: " <> showPoint end <> "]"
showShape (Text loc text) =
  "Text [location: " <> showPoint loc <> ", text: " <> show text <> "]"
```

今度はパターンマッチでデータ構築子を使っている。代数的データ型で列挙しているものが網羅されているかの検査もされる。良い。代数的データ型とパターンマッチがうまく組み合わされていると感じる。

## PureScript by Example 5.14

`showPoint` を再掲する。 `Record` の中身がうまく取り出せているのが分かる。 JavaScript は ES2015 以降で似たような文法が有効になっているので、そこまで違和感はないはずだ。

```
showPoint :: Point -> String
showPoint (Point { x, y }) =
  "(" <> show x <> ", " <> show y <> ")"
```

取り出せるように、組み立てることもできる。

```
origin :: Point
origin = Point { x, y }
  where
    x = 0.0
    y = 0.0
```

ふむ。

## まとめ

代数的データ型の箇所を扱った。明日は `newtype` か。

## 参考

- [PureScript by Example][purescript-by-example]
- [実例による PureScript][purescript-by-example-ja]
- [paf31/purescript-book][paf31/purescript-book]
- [Language Guide][language-guide]
- [Language Guide - Tagged Unions][language-guide-tagged-unions]

## 次回以降の TODO

- PureScript by Example & PureScript Language Guide を読み進める
- `Array` 以外での `do` 記法
- Newtype
- `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-17]: http://qiita.com/bouzuya/items/129b2ab8ba3fa89edaf5
[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-tagged-unions]: https://github.com/purescript/documentation/blob/7a3b93fa98c360ef40b88b736cb48769449d8a9b/language/Types.md#tagged-unions
[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
[language-guide-top-level-declarations]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Syntax.md#top-level-declarations