PureScript by Example の 5.10, 5.11 を読む

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

- ← 14 日目『 [PureScript by Example 5.7 〜を読む - Qiita][2016-12-14] 』
- → 16 日目『 [PureScript by Example 5.12, 5.13, 5.14 を読む - Qiita][2016-12-16] 』

## 概要

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

今日は 5.10 から読んでいく。

※注意事項: 英語と日本語訳では大きな差異がある。`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` のパターンマッチを見た。またガードを書けること、ネストできること、`@` で名前をつけられることも見た。

Language Guide:

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

## PureScript by Example 5.10

`case` 式。パターンマッチは Top-level declaration 以外でもできるらしい。そのための構文が `case` だ。

```
import Data.Array.Partial (tail)
import Data.Foldable (sum)
import Partial.Unsafe (unsafePartial)

lzs :: Array Int -> Array Int
lzs [] = []
lzs xs = case sum xs of
           0 -> xs
           _ -> lzs (unsafePartial tail xs)
```

この場合も `_` のパターンを除くと、コンパイルエラーになる。

## PureScript by Example 5.11

パターンマッチの失敗と部分関数。いままでなんとなく書かれてきた `unsafePartial` のこと。

パターンマッチですべてのパターンが網羅されていない場合、通常 PureScript だとコンパイルエラーになるはずだ。強引に定義しようとすると `unsafePartial` を使えば良い。

```

import Partial.Unsafe (unsafePartial)

partialFunction :: Boolean -> Boolean
partialFunction = unsafePartial \true -> true
```

`false` の場合のパターンを網羅できていないが、コンパイルエラーにはならない。ただし実行すると次のようにエラーとなる。

```
> import Main
> partialFunction false
/Users/bouzuya/.ghq/github.com/paf31/purescript-book/exercises/chapter5/.psci_modules/node_modules/Main/index.js:14
            throw new Error("Failed pattern match at Main line 29, column 19 - line 29, column 42: " + [ v.constructor.name ]);
            ^

Error: Failed pattern match at Main line 29, column 19 - line 29, column 42: Boolean
    at /Users/bouzuya/.ghq/github.com/paf31/purescript-book/exercises/chapter5/.psci_modules/node_modules/Main/index.js:14:19
    at Object.partialFunction (/Users/bouzuya/.ghq/github.com/paf31/purescript-book/exercises/chapter5/.psci_modules/node_modules/Main/index.js:15:11)
    at Object.<anonymous> (/Users/bouzuya/.ghq/github.com/paf31/purescript-book/exercises/chapter5/.psci_modules/node_modules/$PSCI/index.js:6:15)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
```

どんな入力に対しても値を返せる関数を全域関数 (total function) 、そうでないものを部分関数 (partial function) と呼ぶらしい。

PureScript では下記のように重複している場合に警告される。

```
redundantCase :: Boolean -> Boolean
redundantCase true = true
redundantCase false = false
redundantCase false = false
```

上記はエラーにはされないが、警告はされる。

Pursuit:

- [unsafePartial - Partial.Unsafe - purescript-partial - Pursuit][pursuit-partial-unsafe]

実装を見ると……。

https://github.com/purescript/purescript-partial/blob/v1.1.2/src/Partial/Unsafe.purs#L10-L10

```
-- | Discharge a partiality constraint, unsafely.
foreign import unsafePartial :: forall a. (Partial => a) -> a
```

https://github.com/purescript/purescript-partial/blob/v1.1.2/src/Partial/Unsafe.js#L5-L7

```
exports.unsafePartial = function (f) {
  return f();
};
```

`Partial => a` なものを `a` にするだけみたい。

`=>` の話はまたそのうち出てくるはず。おそらく 6 章だろう。

## まとめ

代数的データ型に入ろうかと思ったのだけど、中途半端なので明日へ送る。

## 参考

- [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]
- [unsafePartial - Partial.Unsafe - purescript-partial - Pursuit][pursuit-partial-unsafe]

## 次回以降の TODO

- PureScript by Example & PureScript Language Guide を読み進める
- `Array` 以外での `do` 記法
- Tagged Unions / 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-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
[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/

[pursuit-partial-unsafe]: https://pursuit.purescript.org/packages/purescript-partial/1.1.2/docs/Partial.Unsafe#v:unsafePartial
[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:(:)

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