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以外にトランスパイルする時は役に立つのかもしれない。