Slide 1

Slide 1 text

AltJS を作るなら 多分型変換を入れた方がいい cannorin

Slide 2

Slide 2 text

2 関数型プログラム言語や型システムについての マニアックな知識が必要な部分があります そのようなスライドにはもくもくマークを付けました→ 分からない場合は聞き流して大丈夫なように頑張ります 

Slide 3

Slide 3 text

3 最強の AltJS を作りたい ですよね?

Slide 4

Slide 4 text

4 最強の AltJS とは… ・軽量構文! ・静的型付き!! ・関数型プログラミング!!! ・ JS の資産がそのまま使える!!!! これらだけ なら簡単! どうやれば????

Slide 5

Slide 5 text

5 JS の資産を活用 ・ Definitely Typed というものがある https://github.com/DefinitelyTyped/DefinitelyTyped npm パッケージの TypeScript 用型定義 (.d.ts) がいっぱいある → .d.ts から AltJS 用のバインディングを   自動生成したい!!

Slide 6

Slide 6 text

6 ここで自己紹介 .d.ts から OCaml 系 AltJS (js_of_ocaml, ReScript) 用の バインディングを生成するツールを作っています 他には AltJS コンパイラの中身をいじったり OCaml や F# のツール・ライブラリに contribute したり

Slide 7

Slide 7 text

7 TypeScript の特徴 ・クラスベース OOP ➾ 関数型プログラミングとは相性悪め!(今回はこれの話) ・構造的部分型付け ➾ 多くの TS プログラマは名前的部分型付けのつもりで   書いているので,あまり気にしなくて OK かも ・充実した型操作 ➾ Turing 完全になっちゃうので,ある程度以上は諦める

Slide 8

Slide 8 text

8 関数型 AltJS に変換? ・クラスベース OOP → 関数型プログラミングとは相性悪め!(今回はこれの話) ・構造的部分型付け → 多くの TS プログラマは名前的部分型付けのつもりで   書いているので,あまり気にしなくて OK かも ・充実した型操作 → Turing 完全になっちゃうので,ある程度以上は諦める

Slide 9

Slide 9 text

9 クラスベース OOP の変換 ・ OOP をそのまま入れられるなら OK 例 : F# ベースの AltJS: Fable (C# との連携用に元々入ってる ) ・そうでない場合,以下の要素が問題になる ①メソッドのオーバーロード (関数のオーバーロードは関数型と相性悪い) ②クラス・インターフェースの継承 (何らかの方法で部分型付けをやる必要あり)

Slide 10

Slide 10 text

10 ① オーバーロード 以下のような .d.ts を考えよう

Slide 11

Slide 11 text

11 ① オーバーロード Hindley-Milner 型推論にオーバーロードを加えると決定不能になる [1] → 決定可能になるようにする or 諦める 決定可能になるようにする… → 型クラスを導入する(例 : PureScript ) → 制限された形のオーバーロードのみ受け付けるようにする [2] (難しいので,やってる AltJS は多分ない) 諦める… → 決定不能でもいいか~(例: Fable) → オーバーロードごとに関数をリネームする(例: js_of_ocaml, ReScript) 型 推 論 で き な い か も し れ な い

Slide 12

Slide 12 text

12 ① オーバーロード(型クラス) PureScript を例に… ● オーバーロードされた foo 用の型クラス Fooable を作る ● Number 版と String 版を別々に import して, それぞれ Fooable のインスタンスにする ● すると一個の foo に String を渡しても Number を渡しても使えるようになる → そもそも言語に型クラスを実装するのが超大変 → 自動生成はそんなに大変ではない ( 1 個のメソッドに対して 1 個の型クラスを作る必要があるが…) → ユーザとしては使いやすい (が,型クラス自体が難しい…)

Slide 13

Slide 13 text

13 ① オーバーロード(リネーム) ReScript を例に… ● Number と String に対してそれぞれ fooNumber, fooString を external で定義 (ただし,両者とも同じ foo にコンパイルさせる) ● 使う際は,引数の型に応じて fooNumber か fooString を使い分ける → 言語側の実装はとても楽 ( FFI 対象の名前を指定できるようにするだけ) → 自動生成もリネームするだけなので楽 (リネーム時に名前衝突しないよう気を配る必要あり) → ユーザとしては少し使いづらい

Slide 14

Slide 14 text

14 ① オーバーロード 型クラスは言語機能としてかなり“重たい” ・例えば,存在型と組み合わせると型推論が決定不能になる [3] これに関しては諦めたほうが楽だと思う… ・型クラスで決定不能になるくらいなら最初から決定不能にしても同じ ・リネームはエディタの補完で何とかなる範囲なので,  リネームで頑張りたい

Slide 15

Slide 15 text

15 ② 継承 以下のような .d.ts を考えよう

Slide 16

Slide 16 text

16 ② 継承 素朴にやると大変ヤバい ● 継承したものも含めてメソッド全部追加しちゃお O(n2) で コード増加 ( n: 型の数)

Slide 17

Slide 17 text

17 ② 継承 素朴にやると大変ヤバい ● 継承元の型に変換する関数を足そう d->D.to_B ->B.to_A ->A.foo(42.0)

Slide 18

Slide 18 text

18 ② 継承 素朴にやると大変ヤバい ● 継承元の型には全部一発で変換できるようにするか… O(n2) で コード増加 ( n: 型の数)

Slide 19

Slide 19 text

19 ② 継承 Hindley-Milner 型推論に部分型付けを加えると実用上しんどい [4] → もっと軽量な仕組みで継承を再現したい われわれが求める要件としては, 1. コード増加が O(n2) とかにならないようにしたい 2. 継承元の型には全て一発で変換できるようにしたい(例: D から A ) 3. 外部 (TypeScript) の世界から来た型にのみ上記ができれば十分 → このような型システムの研究はあまりされていないように見える (近いことをやっている論文 :[5] )

Slide 20

Slide 20 text

20 ② 継承 : でもファンクタ使えばいいじゃん? → 継承時の型変数の数の変化が問題になる ● C では型変数 ’ a が増えてしまっている → A.Impl をそのまま include できない ● これを解消するには,’ a もファンクタ の引数として取るしかない → C を異なる ‘ a で使うたびに ファンクタを適用しないといけなくなる ● さすがにそれでは使いづらいのではないか ( AltJS としては OCaml ユーザだけでなく, 既存の JS ユーザも取り込みたいところ)

Slide 21

Slide 21 text

21 ② 継承 : でも row polymorphism 使えばいいじゃん? → オーバーロードされたメソッドが問題になる ● c は a も b も継承していることにしたい ● row polymorphism で部分型になるには, 名前と型が一致してないといけない ● しかし,同じ名前で複数のフィールドを レコード c に定義することはできない ● c でどちらかをリネームすると. row polymorphism が壊れてしまう ● a か b の foo を事前にリネームしておくことも できない(もし別ライブラリで定義されてたら…)

Slide 22

Slide 22 text

22 ② 継承 : row polymorphism + phantom types ・ row polymorphism をそのまま使うのではなく,  「継承している型の列」に対して使う ・「型の列」は phantom type として保持 ・例 : B は A を継承しているので #B と #A を持つ ・この手法ならわれわれの求める要件を満たせる   - コード増加は O(n) に収まる   - 明示的に書く必要はあるが, D→A の変換は一発 → これをきちんと言語機能として組み込めば,   型推論を決定可能に保ちつつ, TypeScript の継承   をうまく翻訳できるのではないだろうか?

Slide 23

Slide 23 text

23 ② 継承 なんにせよ, JavaScript/TypeScript の世界からやってきた型を, 継承関係に従って簡単に変換できるような専用の仕組み が,最強の AltJS を作るためには必要 そして,それは最強の AltJS の 「最強性」を失うことなしに実現できそうな気がする

Slide 24

Slide 24 text

24 参考文献 [1] Dennis M. Volpano and Geoffrey S. Smith. On the complexity of ML typability with overloading. https://ecommons.cornell.edu/handle/1813/7050 [2] Geoffrey S. Smith. Polymorphic Type Inference for Languages with Overloading and Subtyping. https://ecommons.cornell.edu/handle/1813/7070 [3] Sulzmann, Martin & Schrijvers, Tom & Stuckey, Peter. Principal Type Inference for GHC-Style Multi-parameter Type Classes. https://www.researchgate.net/publication/221323263 [1] Dennis M. Volpano and Geoffrey S. Smith. On the complexity of ML typability with overloading. https://ecommons.cornell.edu/handle/1813/7050 [4] François Pottier. Type Inference in the Presence of Subtyping: from Theory to Practice. https://hal.inria.fr/inria-00073205 [5] Fluet, Matthew and Pucella, Riccardo. Phantom Types and Subtyping. https://arxiv.org/abs/cs/0403034