purs --version
0.12.5
前置き
Tuple
data Tuple a b = Tuple a b
簡単にはa かつ bを表す。
レコードがあるので、パフォーマンス的な意味でもあまり使い道は無いはず。
敢えてTuple
を使いたいという場面は限られてきそう。
Either
data Either a b = Left a | Right b
簡単にはa または bを表す。
これを応用して純粋な例外処理にも使える。
例外処理に使う時は慣例的にLeft
がエラーを表す。
Theseとは?
purescript-these
パッケージを参考にしてみる。
data These a b
= This a
| That b
| Both a b
具体例で考えると分かりやすい。
例えば、ユーザーはTwitterアカウントかGithubアカウントのどちらかを持っていないといけないとする。
例えば以下のように書いてみる。
data UserAccount = Either TwitterAccount GithubAccount
上記の実装だとTwitterアカウントとGithubアカウントを同時に持つことができないという意味になってしまう。こうして見るとEither
はXOR的にも見える。
そこで、疑似的には以下のように書くことになる。
UserAccount
is TwitterAccount
OR GithubAccount
OR TwitterAccount AND GithubAccount
これはThese
を使うと簡潔に書ける。
拡張性には乏しいが、知っておくと便利かも。
data UserAccount = These TwitterAccount GithubAccount
3種類以上のデータ型の組み合わせ
Data.Either.Nested
Tuple
とEither
は2つのデータ型しか組み合わせることができない。
原始的には、ネストすることで複数のデータを組み合わせることができる。
ただし、コンパイラは本来Either a (Either b c)
やEither (Either a b) c)
を異なるものとして認識するはずで、同じものとして使うには工夫が必要になってくる。
幸いにもpurescript-either
パッケージにはData.Either.Nested
があり、10個までのネストに対する処理がハードコードされている。
ドキュメントの使用例が分かりやすい。
data Color = Red Number | Green Number | Blue Number
fromEither3 :: Either3 Number Number Number -> Color
fromEither3 = either3 Red Green Blue
toEither3 :: Color -> Either3 Number Number Number
toEither3 (Red v) = in1 v
toEither3 (Green v) = in2 v
toEither3 (Blue v) = in3 v
実用上は確かに10個もあれば十分そう。
11個以上のネストをする時はVariant
を使うと良い?
(いわゆるextensibleというやつで、Proxyを筆頭とした型レベルの知識が必要になるらしい。)
複数のTuple
これに関してはTuple
を使うまでもなくレコードが良い仕事をしてくれるし、トランスパイルしたときのパフォーマンスもレコードのほうが良いはず。
JavaScript以外にトランスパイルする時は役に立つのかもしれない。