PureScript by Example 4 章の終わりと 5 章の冒頭を読む

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

- ← 11 日目『 [PureScript by Example 4 章の後半を読む - Qiita][2016-12-11] 』
- → 13 日目『 [PureScript by Example の 5 章の前半を読む - Qiita][2016-12-13] 』

## 概要

[PureScript by Example][purescript-by-example] と [PureScript Language Guide][language-guide] を見ながら進めていく。今日は [PureScript by Example の 4 章][purescript-by-example-4]の残りと [PureScript by Example の 5 章][purescript-by-example-5]の前半を読む。

PureScript の 0.10.3 が出たことに合わせているのか、 [Language Guide を含むドキュメントが Wiki から purescript/documentation リポジトリに移動されたようだ][purescript/documentation]。

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

## PureScript by Example 4.16

PureScript by Example の 4 章のために用意された `Data.Path` モジュールを使って、仮想のファイルシステムで動く関数を作っていく。

[purescript-book の `Data.Path`][purescript-book-data-path]

```
> import Data.Path (root, ls, filename, size, isDirectory)
> :t root
Path

> :t ls
Path -> Array Path

> :t filename
Path -> String

> :t size
Path -> Maybe Int

> :t isDirectory
Path -> Boolean

> root
/

> isDirectory root
true

> ls root
[/bin/,/etc/,/home/]
```

確かに。

## PureScript by Example 4.17

```
allFiles :: Path -> Array Path
allFiles file = file : concatMap allFiles (ls file)

allFiles' :: Path -> Array Path
allFiles' file = file : do
  child <- ls file
  allFiles' child
```

`cons` の operator alias である `(:)` を使っている。不変の array では `cons` のパフォーマンスに問題があるので、linked list か sequence を使え、とのこと。ふむ。[実装的には `Array.prototype.concat` みたい](https://github.com/purescript/purescript-arrays/blob/v3.1.0/src/Data/Array.js#L73)。

Pursuit:

- [cons - Data.Array - purescript-arrays - Pursuit][pursuit-arrays-cons]
- [(:) - Data.Array - purescript-arrays - Pursuit][pursuit-arrays-cons-op]

これで 4 章は終わり。次は 5 章。

## PureScript by Example 5.1

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

この章ではシンプルなベクターグラフィックスの操作ライブラリを書くようだ。

## PureScript by Example 5.2

ソースコードは [paf31/purescript-book の exercises/chapter5/][purescript-book-chapter-5]

`bower.json` の `dependencies` は次のとおりだ。

```
"purescript-arrays": "^3.0.0"
"purescript-console": "^2.0.0"
"purescript-globals": "^2.0.0"
"purescript-math": "^2.0.0"
```

Pursuit:

- [purescript-arrays - Pursuit][pursuit-arrays]
- [purescript-console - Pursuit][pursuit-console]
- [purescript-globals - Pursuit][pursuit-globals]
- [purescript-math - Pursuit][pursuit-math]

[`src/Data/Picture.purs`][purescript-book-chapter-5-picture] を見ると次のように `import` されている。

```
module Data.Picture where

import Prelude

import Data.Foldable (foldl)
import Global as Global
import Math as Math
```

`as` キーワードを使っている。

Language Guide:

[Qualified Imports - Language Guide][language-guide-qualified-imports]

これを使うと、名前の衝突を回避できる。

```
> import Global as Global
> :t isNaN
Error found:
in module $PSCI
at  line 1, column 1 - line 1, column 2

  Unknown value isNaN


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


> :t Global.isNaN
Number -> Boolean

> :t Global.encodeURI
String -> String
```

ちなみに例が明示されていないが、組み合わせて使うこともできるようだ。

```
> import Global (isNaN) as Global
> :t Global.isNaN
Number -> Boolean

> :t Global.encodeURI
Error found:
in module $PSCI
at  line 1, column 1 - line 1, column 9

  Unknown value Global.encodeURI


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

## まとめ

すごく中途半端だけど、時間の都合でここで区切り。

4 章を終えた。 5 章に入ったけど、まだ代数的データ型もパターンマッチも出てきていない……。

## 参考

- [PureScript by Example][purescript-by-example]
- [実例による PureScript][purescript-by-example-ja]
- [paf31/purescript-book][paf31/purescript-book]
- [Language Guide][language-guide]
- [Language Guide - Qualified Imports][language-guide-qualified-imports]
- [Pursuit - cons - Data.Array - purescript-arrays][pursuit-arrays-cons]
- [Pursuit - (:) - Data.Array - purescript-arrays][pursuit-arrays-cons-op]
- [Pursuit - purescript-arrays][pursuit-arrays]
- [Pursuit - purescript-console][pursuit-console]
- [Pursuit - purescript-globals][pursuit-globals]
- [Pursuit - purescript-math][pursuit-math]

## 次回以降の 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-13]: http://qiita.com/bouzuya/items/a49463871a96459d7083
[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-ja]: http://hiruberuto.bitbucket.org/purescript/
[try-purescript]: http://try.purescript.org/
[language-guide]: https://github.com/purescript/documentation/blob/3ad760bdd4488a9597f9f88b1bc106ec23036148/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:(:)