[https://twitter.com/yyu:embed]
protocolはassociatedtypeといった、いわゆる存在型しか扱うことができない。あるprotocolに対してextensionで機能を与えるとき、associatedtypeには必ずなんらかの具体的な型を入れることが求められる。protocol/extensionは型に基づいて関数を探すような動きをするため、どこかでは具体的な型が必要となるが、たとえば任意の型AについてList[A]を最終的に利用するようなextensionを書きたい時がある。このトークでは、カリー=ハワード同型対応を利用してassociatedtypeのような存在型からジェネリクスを無理やり生み出す方法について考察する。
今日はちょっと、プロトコルとエクステンション、そのなかにどうGenericsを放り込むかについて軽く解説できれば
今日の流れ
変わった実装を紹介しつつメソッドを実行することでお伝えしたい
ProtocolExtensionについておさらいをして、最終的な解決方法を述べてまとめ。
Scalaエンジニアです。暗号も趣味。量子プログラミング。
タプルとリストというデータ構造について。
タプルは、AとBの型を持つのが合計2つあるというもの
リストは、Aが0以上、100個でも良いしもっとでも良い。
リストにいろいろな方を詰め込めたら良いんじゃないかと思ったことはないでしょうか?
Anyのリストを作る? 取り出したときにキャストが必要で、型が失われますね。
Heterogeneous List、
Listとおなじ?
いいえ、
このデータ構造は面白くて、中の値と型を対応付けておぼえておける
Int, Bol, Stringが順序とともに詰め込める。
リストは混在したものを表現できない
今日は、2つのHListを取ってきてくっつけることをしてみる
普通のリストのAppend
型パラメーターを1つしか取らないようなAppendでは無理がありそう
Javaだと大変そうだが、SwiftはProtocolExtensionがあるので面白く実装できる
知っている人もいるかと思うがおさらいしていこうと思います。
JavaのInterfaceのようだと言われることがある
型パラメータAを受け取ってJsonに変換するようなもの。Userというクラスを作って、JSONWriteに適合していればJSONにできる
確かに似ているように見える
では、ありがちなケースとしてIntや、他人のライブラリのデータ構造を改造したい場合がある
JavaはAdapterパターンと言って、Integerを拡張したものを作るしか手が打てないことがある
しかしSwiftはExtensionですでにFixした型を拡張できる
型で機能を探してくるということができる。
どういうことか
型で機能を探してくるとはどういうことか、これはOverrodeのこと
IntとIntなら足す、文字列と文字列なら結合する
Swiftは引数の型から適切な関数を探してくるからこういう事ができる
こんな事が、ExtensionとProtocolで模倣できる
where句を伴うことができて、逆、overlodeではProtocol Extensionを再現できない
さて、appendを作れないか
もう一度普通のListのAppendをみる
A(最初の引数)によって分岐している。
長さ1以上なら繰り返すAがnilなら、2番目の引数を返す。そういう再帰的な処理をしている
配列の長さはruntimeの情報。
われわれはHListの型でディスパッチした機能を変更したい。
型情報はコンパイルタイムの情報だから、コンパイルタイムにこちらの機能を使うのかあちらの機能を使うのかディスパッチしたい。
型情報を使うにはProtocol Extensionがよい。
いずれもHListに適合したassociatedtypeを持つ
まずはnilのケースからやっていきましょう
App1はExtensionを作るときにGenerics、型パラメーターを引っ張ってこられないので、App1でHlistの方をもってくるために作った
からのHListと何かのHListをもってきたら2番めの引数だけ返す
長さが1以上なら
問題を整理
where句をいくらいじっても、もうHListに適合していますと言われてコンパイルが成功しない
普通のリストのAppendはAppend自身を再帰的にもってきていた。そのもってきていたAppendをどこから持ってくるのか。
App1がもってこられないのは別の方を使えば良い。型パラメーターも足りなかったのでApp1〜App3まで用意してやった
でもこれではRightとResultに何を入れるのかという問題が残る
思い切ってApp5まで増やした
EVはHAppendに適合している
かんですがこうしました
何がどうなっているかと思われるかもしれない。
Aは1と2が入っていて、Bは3と4が入っている。CはA+Bが等しいと行っている。
CはAとBをアペンドした結果になっているべき
そこへDを登場させる。Aの先頭にDが突っ込んである。Bは上のBと同じ
Resultの四季がややこしいがmAの先頭にDを足したものにBを足す。
一瞬で理解するのは大変だと思いますが、こうするとうまく型がつく。
気合が途中であったが、ようやくAppendが誕生
使ってみましょう
何が何やらさっぱりわからないと思いますが
どうやってもEVの型を推論してくれなくて
こういう有様
Scalaならこの程度なら作れるのですが型推論機がまだSwiftは途上?
こういう色々なデータ構造を入れられる構造がある
Protocol と Extensionを駆使すると作れる
HListのN番目の要素を持ってくるようなメソッドも作れる
型推論機は途上なので、自分で作っておいてなんですが、プロダクションで使うには問題があると思う
処理系がもっと良くなればハッピーになると思います
参考文献
上が原著、下が翻訳書です。
型システム入門。
巷では難しいと言われがち。たしかにオライリーとか、プログラミング入門のホントは毛色が違うところがある、でも平易なところから高度なところまでカバーしているすごく良い本。興味を持たれたら手にとってください。
ご清聴ありがとうございました。