LoginSignup
2
1

More than 5 years have passed since last update.

PureScriptのTheseとネスト化Either

Posted at
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

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

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1