PureScript by Example の 5 章の前半を読む

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

- ← 12 日目『 [PureScript by Example 4 章の終わりと 5 章の冒頭を読む][2016-12-12] 』
- → 14 日目『 [PureScript by Example 5.7 〜を読む - Qiita][2016-12-14] 』

## 概要

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

今日は [PureScript by Example の 5 章][purescript-by-example-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) を扱うらしい。

Language Guide:

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

## PureScript by Example 5.3

簡単なパターンマッチの例。

```
gcd :: Int -> Int -> Int
gcd n 0 = n
gcd 0 m = m
gcd n m = if n > m
            then gcd (n - m) m
            else gcd n (m - n)
```

イメージどおりに動く (雑) 。引数で `n 0` `0 m` `n m` というパターンを用意し、それにマッチした場合の結果を書いておく。

## PureScript by Example 5.4

シンプルなパターン。イメージどおりに動く (雑) 。 `Number` `String` `Char` `Boolean` のリテラルとワイルドカードパターン (`_`) が動作すると書いてある。なるほど。

```
fromString :: String -> Boolean
fromString "true" = true
fromString _      = false

toString :: Boolean -> String
toString true  = "true"
toString false = "false"
```

代数的データ型が章の名に含まれているので、それらのパターンマッチも出てくるはずだ。

これらの例でぼくが面白いと感じる点は `fromString _` や `toString false` の行を削除するとコンパイルエラーになることだ。代数的データ型の話がまだ出てきていないので書きづらいのだけど、 `Boolean` は `true` と `false` からなる。その両方を網羅していない場合はコンパイルエラーになる。

## PureScript by Example 5.5

`|` でガードを書けるらしい。さらに分けられる。ふむ。

```
gcd :: Int -> Int -> Int
gcd n 0 = n
gcd 0 n = n
gcd n m | n > m     = gcd (n - m) m
        | otherwise = gcd n (m - n)
```

## PureScript by Example 5.6

今日は `Array` パターンで終わろう。`Array` リテラルでマッチできる。

```
isEmpty :: forall a. Array a -> Boolean
isEmpty [] = true
isEmpty _ = false

takeFive :: Array Int -> Int
takeFive [0, 1, a, b, _] = a * b
takeFive _ = 0
```

```
> import Prelude
> :paste
… let
…   takeFive [0, 1, a, b, _] = a * b
…   takeFive _ = 0
…
> takeFive [0, 1, 2, 3, 4]
6

> takeFive [1, 2, 3, 4, 5]
0

> takeFive []
0

> takeFive [0, 1, 2, 3, 4, 5]
0

```

なるほど。これは良い。

`Array` パターンは固定長を前提としているらしい。可変長にしたいなら `Data.List` を使えと。なるほど。

[language-guide-top-level-declarations]: https://github.com/purescript/documentation/blob/f48ba1ee7761446e1ae75ee806e51688c1937297/language/Syntax.md#top-level-declarations

## 参考

- [PureScript by Example][purescript-by-example]
- [実例による PureScript][purescript-by-example-ja]
- [paf31/purescript-book][paf31/purescript-book]
- [Language Guide][language-guide]
- [Language Guide - Top-level declarations][language-guide-top-level-declarations]

## 次回以降の TODO

- PureScript by Example & PureScript Language Guide を読み進める
- `Array` 以外での `do` 記法
- Tagged Unions / Newtype
- `psc-package`
- PureScript IDE の導入
- [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-14]: http://qiita.com/bouzuya/items/14ca2a2cd9c0bb01653d
[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/

[paf31/purescript-book]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/
[language-guide-qualified-imports]: https://github.com/purescript/documentation/blob/3ad760bdd4488a9597f9f88b1bc106ec23036148/language/Modules.md#qualified-imports
[purescript-book-chapter-5]: https://github.com/paf31/purescript-book/tree/8ad7d2af75ad4c795d5075018e9ee45005799e6f/exercises/chapter5
[purescript-book-chapter-5-picture]: https://github.com/paf31/purescript-book/blob/8ad7d2af75ad4c795d5075018e9ee45005799e6f/exercises/chapter5/src/Data/Picture.purs
[pursuit-arrays]: https://pursuit.purescript.org/packages/purescript-arrays/3.1.0
[pursuit-console]: https://pursuit.purescript.org/packages/purescript-console/2.0.0
[pursuit-globals]: https://pursuit.purescript.org/packages/purescript-globals/2.0.0
[pursuit-math]: https://pursuit.purescript.org/packages/purescript-math/2.0.0
[pursuit-arrays-cons]: https://pursuit.purescript.org/packages/purescript-arrays/3.1.0/docs/Data.Array#v:cons
[pursuit-arrays-cons-op]: https://pursuit.purescript.org/packages/purescript-arrays/3.1.0/docs/Data.Array#v:(:)