let rec の型推論と多相型

忘れてしまわないうちにまとめておきます。 let rec を型推論するときにできるかぎり多相型になるように推論するには、まず変数の依存性グラフを Strongly Connected Components (SCC) に分解することで、より小さい let と let rec のネストに変換を行なってから型推論するということ。また、型シグネチャがすでに付いている式への依存を依存性グラフの辺から取り除くことで、let rec 内を多相型に推論できる可能性を上げることができる。
7
K. Sakaguchi @pi8027

やっぱり specialize 挟んでも推論一発で終わるっていうのは嘘な気がするし、自前の推論器で型がおかしくなるケースは作れた。@mayahjp さんを質問攻めにする会が必要!

2010-11-17 08:06:48
mayah@節電中 @mayahjp_old

@pi8027 それ自分が考えているのより強い型推論じゃないかなー、というわけで例を下さい。

2010-11-17 10:46:27
K. Sakaguchi @pi8027

しかしこれくらい推論してくれないと困る……。

2010-11-17 12:21:53
mayah@節電中 @mayahjp_old

@pi8027 これぐらい何の問題もなく推論できると思うんですけど、どういう結果がでてるんでしょう。というか github から source 落としてきて走らせればいいのか

2010-11-17 13:20:10
K. Sakaguchi @pi8027

@mayahjp 上から調べていくので、下に定義のある名前の型を取ってこれないのです。もし上手く順序を入れ替えたとしても、一部の再帰関数などで同じ現象が起きる気がします。

2010-11-17 15:52:30
日比野 啓 (Kei Hibino) @khibino

@pi8027 @mayahjp 構文解釈木の任意の部分式の型をunifyで特殊化していくんだよね? < 上から調べていくので、下に定義のある名前の型を取ってこれないのです。

2010-11-17 17:56:12
日比野 啓 (Kei Hibino) @khibino

@pi8027 @mayahjp でもlet多相にしたかったら、その操作の前に letを展開する操作が必要なんじゃないかな

2010-11-17 17:57:12
日比野 啓 (Kei Hibino) @khibino

@pi8027 @mayahjp ところでgistにあるコードの # は case ... of と思えば良い?

2010-11-17 17:59:10
日比野 啓 (Kei Hibino) @khibino

@pi8027 @mayahjp unifyの操作は再帰で一発なんじゃないかと

2010-11-17 18:01:08
日比野 啓 (Kei Hibino) @khibino

@pi8027 @mayahjp とここまで書いて、letrec の多相はどうやるんだかちゃんと分かっていないことに気がついた

2010-11-17 18:09:41
Jun Furuse @camlspotter

fresh な型変数aを与えておいて、bodyを推論し、単一化終わった後のS(a)をgeneralizeする。 RT @khibino: @pi8027 @mayahjp とここまで書いて、letrec の多相はどうやるんだかちゃんと分かっていないことに気がついた

2010-11-17 18:19:21
日比野 啓 (Kei Hibino) @khibino

おお、ありがとうございます。< @camlspotter fresh な型変数aを与えておいて、bodyを推論し、単一化終わった後のS(a)をgeneralizeする。RT @khibino: @pi8027 @mayahjp .. letrec の多相はどうやるんだか ..

2010-11-17 18:29:41
Jun Furuse @camlspotter

副作用があるとS(a)の計算が要らなくて超クールなのですが。cf ocaml RT @khibino: おお、ありがとうございます。< @camlspotter fresh な型変数aを与えておいて、bodyを推論し、単一化終わった後のS(a)をgeneralizeする。

2010-11-17 18:33:11
日比野 啓 (Kei Hibino) @khibino

unifyを型変数への代入で、ということですよね。初めて見たときはちょっと感動しました RT @camlspotter 副作用があるとS(a)の計算が要らなくて超クールなのですが。cf ocaml RT @khibino: おお、ありがとうございます。

2010-11-17 18:38:52
Jun Furuse @camlspotter

pure ではそのへんをどう頑張るか、なんか研究あったと思いますが、わざわざ自縛したうえでの競争なんで興味が持てず。まあ普通でいいんじゃん、はじめは。 RT @khibino: unifyを型変数への代入で、ということですよね。初めて見たときはちょっと感動しました

2010-11-17 18:43:42
Jun Furuse @camlspotter

ごめん、body は definition ね。in の後の式じゃないよ。 RT @camlspotter: fresh な型変数aを与えておいて、bodyを推論し、単一化終わった後のS(a)をgeneralizeする。

2010-11-17 19:06:27
日比野 啓 (Kei Hibino) @khibino

了解です RT @camlspotter ごめん、body は definition ね。in の後の式じゃないよ。 RT @camlspotter: fresh な型変数aを与えておいて、bodyを推論し、単一化終わった後のS(a)をgeneralizeする。

2010-11-17 19:14:17
mayah@節電中 @mayahjp_old

@khibino @camlspotter @pi8027 おっと、みていない間にこんなに。let rec はそれでいいんですが、let rec id x = x and hoge () = id 1 みたいにすると、id は int -> int と推論されてしまう。

2010-11-17 19:17:59
mayah@節電中 @mayahjp_old

@khibino @camlspotter @pi8027 で、@pi8027 さんのやつは let rec でつなぐと id の型が残念になってしまうので (多相型じゃなくなる)、ちょっと違うことをやらないといけない。まあ単純に Haskell の型推論なんですが。

2010-11-17 19:20:28
mayah@節電中 @mayahjp_old

この場合どうすんだっけ、あとで制約条件とくのなら簡単なんだが Haskell はどうやって実装してるんだっけな

2010-11-17 19:21:22
mayah@節電中 @mayahjp_old

GHC でやったらやっぱちゃんと id の型は t -> t なので、let rec みたいなことにはならない。

2010-11-17 19:27:13
おしいれのぼうけん @osiire

こういうことですね。 # let rec id : 'a. 'a -> 'a = fun x -> x and hoge () = id 1;; val id : 'a -> 'a = <fun> val hoge : unit -> int = <fun>

2010-11-17 19:30:48
日比野 啓 (Kei Hibino) @khibino

うーん、OCamlと同じやりかたでは多相にできないんですね ... @osiire @mayahjp @khibino @camlspotter @pi8027

2010-11-17 19:39:41