この記事は (bouzuya) PureScript Advent Calendar 2016 の 16 日目。 (bouzuya) PureScript Advent Calendar 2016 は bouzuya の PureScript 学習の記録だ。
- ← 15 日目『 PureScript by Example の 5.10, 1.11 を読む - Qiita 』
- → 17 日目『 PureScript by Example の 5.15 を読む - Qiita 』
概要
PureScript by Example を PureScript Language Guide や Pursuit を見ながら進めていく。
今日は 5.12 から読んでいく。ソースコードの例は purescript-book の chapter5 にある。
※注意事項: 英語と日本語訳では大きな差異がある。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
のパターンマッチを見た。またガード・パターンマッチのネスト・ @
で名前付け・ case
式・部分関数と unsafePartial
を見た。
Language Guide:
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
他の例として 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
- paf31/purescript-book
- Language Guide
- Language Guide - Tagged Unions
次回以降の TODO
- PureScript by Example & PureScript Language Guide を読み進める
-
Array
以外でのdo
記法 - Newtype
psc-package
- 24 Days of PureScript, 2016
- 24 Days of PureScript, 2014
- 某氏の記事の紹介
- github.com/purescript のコードを読む
- github.com/purescript-node のコードを読む
- github.com/purescript-contrib のコードを読む