この記事は (bouzuya) PureScript Advent Calendar 2016 の 15 日目。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録だ。
- ← 14 日目『 PureScript by Example 5.7 〜を読む - Qiita 』
- → 16 日目『 PureScript by Example 5.12, 5.13, 5.14 を読む - Qiita 』
概要
PureScript by Example を PureScript Language Guide や Pursuit を見ながら進めていく。
今日は 5.10 から読んでいく。
※注意事項: 英語と日本語訳では大きな差異がある。0.10.x
に対応している英語の側で進める。
- PureScript by Example 2016-12-05 時点で 0.10.x 向け
- 実例による PureScript 2016-12-05 時点で 0.7 向け
- PureScript Language Guide 対象バージョン不明
前回のおさらい
この章では代数的データ型 (algebraic data type) とパターンマッチ (pattern matching) および行多相 (row polymorphism) を扱うらしい。
Number
String
Char
Boolean
Array
Record
のパターンマッチを見た。またガードを書けること、ネストできること、@
で名前をつけられることも見た。
Language Guide:
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:
実装を見ると……。
-- | Discharge a partiality constraint, unsafely.
foreign import unsafePartial :: forall a. (Partial => a) -> a
exports.unsafePartial = function (f) {
return f();
};
Partial => a
なものを a
にするだけみたい。
=>
の話はまたそのうち出てくるはず。おそらく 6 章だろう。
まとめ
代数的データ型に入ろうかと思ったのだけど、中途半端なので明日へ送る。
参考
- PureScript by Example
- 実例による PureScript
- paf31/purescript-book
- Language Guide
- Language Guide - Top-level declarations
- unsafePartial - Partial.Unsafe - purescript-partial - Pursuit
次回以降の TODO
- PureScript by Example & PureScript Language Guide を読み進める
-
Array
以外でのdo
記法 - Tagged Unions / Newtype
- 代数的データ型
psc-package
- 24 Days of PureScript, 2016
- 24 Days of PureScript, 2014
- 某氏の記事の紹介
- github.com/purescript のコードを読む
- github.com/purescript-node のコードを読む
- github.com/purescript-contrib のコードを読む