寄付窓口はこちら

protocol/extensionにジェネリクスを入れたい | try! Swift Tokyo 2019 1-6

[https://twitter.com/yyu:embed]

protocolはassociatedtypeといった、いわゆる存在型しか扱うことができない。あるprotocolに対してextensionで機能を与えるとき、associatedtypeには必ずなんらかの具体的な型を入れることが求められる。protocol/extensionは型に基づいて関数を探すような動きをするため、どこかでは具体的な型が必要となるが、たとえば任意の型AについてList[A]を最終的に利用するようなextensionを書きたい時がある。このトークでは、カリー=ハワード同型対応を利用してassociatedtypeのような存在型からジェネリクスを無理やり生み出す方法について考察する。

f:id:niwatako:20190321120009j:plain

今日はちょっと、プロトコルとエクステンション、そのなかにどうGenericsを放り込むかについて軽く解説できれば

今日の流れ

f:id:niwatako:20190321120108j:plain

変わった実装を紹介しつつメソッドを実行することでお伝えしたい

ProtocolExtensionについておさらいをして、最終的な解決方法を述べてまとめ。

f:id:niwatako:20190321120146j:plain

筑波大学で型システムやプログラミング言語をやっていました

f:id:niwatako:20190321120153j:plain

Scalaエンジニアです。暗号も趣味。量子プログラミング。

f:id:niwatako:20190321120234j:plain

タプルとリストというデータ構造について。

タプルは、AとBの型を持つのが合計2つあるというもの

リストは、Aが0以上、100個でも良いしもっとでも良い。

リストにいろいろな方を詰め込めたら良いんじゃないかと思ったことはないでしょうか?

Anyのリストを作る? 取り出したときにキャストが必要で、型が失われますね。

f:id:niwatako:20190321120354j:plain

Heterogeneous List、

f:id:niwatako:20190321120416j:plain

Listとおなじ?

f:id:niwatako:20190321120424j:plain

いいえ、

このデータ構造は面白くて、中の値と型を対応付けておぼえておける

f:id:niwatako:20190321120453j:plain

Int, Bol, Stringが順序とともに詰め込める。

リストは混在したものを表現できない

今日は、2つのHListを取ってきてくっつけることをしてみる

f:id:niwatako:20190321120536j:plain

普通のリストのAppend

型パラメーターを1つしか取らないようなAppendでは無理がありそう

f:id:niwatako:20190321120611j:plain

Javaだと大変そうだが、SwiftはProtocolExtensionがあるので面白く実装できる

知っている人もいるかと思うがおさらいしていこうと思います。

JavaのInterfaceのようだと言われることがある

f:id:niwatako:20190321120650j:plain

型パラメータAを受け取ってJsonに変換するようなもの。Userというクラスを作って、JSONWriteに適合していればJSONにできる

f:id:niwatako:20190321120717j:plain

確かに似ているように見える

では、ありがちなケースとしてIntや、他人のライブラリのデータ構造を改造したい場合がある

JavaはAdapterパターンと言って、Integerを拡張したものを作るしか手が打てないことがある

しかしSwiftはExtensionですでにFixした型を拡張できる

f:id:niwatako:20190321120802j:plain

型で機能を探してくるということができる。

どういうことか

型で機能を探してくるとはどういうことか、これはOverrodeのこと

f:id:niwatako:20190321120857j:plain

IntとIntなら足す、文字列と文字列なら結合する

Swiftは引数の型から適切な関数を探してくるからこういう事ができる

f:id:niwatako:20190321120920j:plain

こんな事が、ExtensionとProtocolで模倣できる

f:id:niwatako:20190321120934j:plain

where句を伴うことができて、逆、overlodeではProtocol Extensionを再現できない

f:id:niwatako:20190321121030j:plain

さて、appendを作れないか

f:id:niwatako:20190321121056j:plain

もう一度普通のListのAppendをみる

A(最初の引数)によって分岐している。

f:id:niwatako:20190321121115j:plain

長さ1以上なら繰り返すAがnilなら、2番目の引数を返す。そういう再帰的な処理をしている

配列の長さはruntimeの情報。

われわれはHListの型でディスパッチした機能を変更したい。

型情報はコンパイルタイムの情報だから、コンパイルタイムにこちらの機能を使うのかあちらの機能を使うのかディスパッチしたい。

型情報を使うにはProtocol Extensionがよい。

f:id:niwatako:20190321121233j:plain

いずれもHListに適合したassociatedtypeを持つ

まずはnilのケースからやっていきましょう

f:id:niwatako:20190321121259j:plain

App1はExtensionを作るときにGenerics、型パラメーターを引っ張ってこられないので、App1でHlistの方をもってくるために作った

からのHListと何かのHListをもってきたら2番めの引数だけ返す

f:id:niwatako:20190321121355j:plain

長さが1以上なら

f:id:niwatako:20190321121409j:plain

問題を整理

f:id:niwatako:20190321121418j:plain

where句をいくらいじっても、もうHListに適合していますと言われてコンパイルが成功しない

普通のリストのAppendはAppend自身を再帰的にもってきていた。そのもってきていたAppendをどこから持ってくるのか。

App1がもってこられないのは別の方を使えば良い。型パラメーターも足りなかったのでApp1〜App3まで用意してやった

でもこれではRightとResultに何を入れるのかという問題が残る

f:id:niwatako:20190321121535j:plain

思い切ってApp5まで増やした

EVはHAppendに適合している

かんですがこうしました

f:id:niwatako:20190321121602j:plain

何がどうなっているかと思われるかもしれない。

Aは1と2が入っていて、Bは3と4が入っている。CはA+Bが等しいと行っている。

CはAとBをアペンドした結果になっているべき

そこへDを登場させる。Aの先頭にDが突っ込んである。Bは上のBと同じ

Resultの四季がややこしいがmAの先頭にDを足したものにBを足す。

f:id:niwatako:20190321121713j:plain

一瞬で理解するのは大変だと思いますが、こうするとうまく型がつく。

f:id:niwatako:20190321121726j:plain

気合が途中であったが、ようやくAppendが誕生

使ってみましょう

f:id:niwatako:20190321121747j:plain

何が何やらさっぱりわからないと思いますが

どうやってもEVの型を推論してくれなくて

f:id:niwatako:20190321121759j:plain

こういう有様

f:id:niwatako:20190321121819j:plain

f:id:niwatako:20190321121826j:plain

Scalaならこの程度なら作れるのですが型推論機がまだSwiftは途上?

こういう色々なデータ構造を入れられる構造がある

Protocol と Extensionを駆使すると作れる

HListのN番目の要素を持ってくるようなメソッドも作れる

型推論機は途上なので、自分で作っておいてなんですが、プロダクションで使うには問題があると思う

処理系がもっと良くなればハッピーになると思います

f:id:niwatako:20190321121941j:plain

参考文献

f:id:niwatako:20190321121950j:plain

上が原著、下が翻訳書です。

型システム入門。

巷では難しいと言われがち。たしかにオライリーとか、プログラミング入門のホントは毛色が違うところがある、でも平易なところから高度なところまでカバーしているすごく良い本。興味を持たれたら手にとってください。

ご清聴ありがとうございました。