Wadlerのノートがまだよくわからん
なんかやっぱまだ混乱してるっぽい。Wadlerのノートの話なんだが、LFixとFixとGFixがようわからんとか。WadlerのノートにあるLFixとfold(という名前はFixに対して、使うので、ここではcataと書いておく)やらinの定義を、Haskellで素直に書くとこうなる。ついでに、普通の(?)foldの定義を併記しておく
{-# OPTIONS -fglasgow-exts #-} newtype LFix f = Build (forall x.(f x -> x) -> x) cata :: (Functor f)=>(forall x.(f x -> x)->(LFix f)->x) cata k (Build t) = t k inF :: (Functor f) => f (LFix f) -> (LFix f) inF s = Build (\k -> k (fmap (cata k) s)) outF :: (Functor f) => (LFix f) -> f (LFix f) outF = cata (fmap inF) newtype Fix f = In (f (Fix f)) out (In a) = a fold :: forall f.(Functor f) => (forall x.(f x -> x) -> (Fix f) -> x) fold g = g . fmap (fold g) . out
定義から、自動的に
cata k (inF s) = cata k (Build (\k -> k (fmap (cata k) s))) = k (fmap (cata k) s) fold k (In s) = k . (fmap (fold k)) . out (In s) = k (fmap (fold k) s)
が従う。つまり、foldもcataも(Fix f)や(LFix f)から、任意のf代数への射を与える。これが一意であることは自明でないので、Wadlerのノートでは、weakly initial algebraと呼んでいる。
で、LFixとFixが一致するのかという話。Fixの定義は、単に、f (Fix f)と(Fix f)が同型になると言ってるだけなんだよなぁ。関手fの不動点は、多分一般には沢山存在するので、別段それとLFixを同一視するa prioriな理由はないはず。けど、Haskellでは、少なくともあるクラスのFunctorに対しては、最小不動点と最大不動点が一致して、不動点は一意に決まる(ホントかよ)のか?ていうか、最小・最大というのは包含関係について最小・最大という理解でいいんだろうか?まあ、仮にそうだとしても、LFixとGFixの一致は何によって保証されてるのか、よくわからん。勿論、直接的には、遅延評価によってというのが答えなんだろうけど、なんか狐に化かされた感がするというか、説明になってないというか・・・
別の道。LFixもFixもweakly initial algebraになので、こいつらが実際に、initial algebraであることを言ってしまえば、LFixとFixが一致することは言えるけど、それを言うには、Wadlerのノートの条件(3)(4)がいえればよく、そのためには多分parametricity theoremが必要で、Haskellでparametricity theoremを保証するのは何なのかという別の問題が。そもそも、ちゃんとしたsemanticsがないので、証明できるような類のもんではないのかもしれんけど、Acid Rain Theoremとか、あのへんの面白い定理の証明は、parametricity theoremに根拠を持ってたりするので、Haskellで融合変換が使えるか否かというのに、直接影響を与える気がする。
ほんでもって、よく見ると(よく見なくても)、cataの定義には、どこにも再帰が入ってないのに対して、foldの定義はそうではない。fixpoint recursionが存在すると、parametricity theoremは制限を受けないといけなくなる(というようなことは、Wadlerの"Theorems for free!"に書いてある)ので、つまりまあ、cataの方は、純粋にSystem Fの範囲で定義できて、parametriciy theoremが成立するようなモデルであれば、LFix fが確かに、f-始代数を与えることを証明できる(多分)けど、foldの方は、そうではないとか。普通の実用的言語では、fixpoint recursionは存在して、parametricity theoremは(制限された形でしか)適用できず、Haskellのようにnon-strictな言語ではLFixやFixが始代数になることは別の手段で言わないといけないと思う。strictな言語の場合は、parametricity theoremの適用に悩む必要はないのかな、たぶん
別に、こんなことを理解したところで、何の役にも立ちはしないんだけど・・・
オレは『納得』したいだけだ!『納得』は全てに優先するぜッ!!でないとオレは『前』へ進めねぇッ!
関係ありそうな仕事(どっちもちゃんと読んでないけど)
・A Formalization of Hylomorphism Based Deforestation with an Application to an Extended Typed Lambda-Calculus
・Shortcut fusion is correct
http://www.crab.rutgers.edu/~pjohann/jfp01.pdf
いずれも、Fixが〜LFixが〜始代数が〜という話ではなくて、タイトル通り、融合変換の正当性の話。まあ、始代数がどうとかより、融合変換が成立するかの方が重要とは思うけど。2000年前後の仕事なので、今はもっとなんかあるかもしれない。どうでもいいけど、recursive typeとかalgebraic data typeとかinductive typeとか、違いがわかんね
後者の論文で使われてる体系PolyPCFは、System Fにfixpoint recursionとリストを付け加えただけに見える。Pittsのparametric polymorphisms and operational equivalenceには、このPolyPCFの範疇では、このリストが、多相型forall x.x->(a->x->x)->xと"observationally isomorphic"(要するに、一方から他方への写像が存在して、互いに逆関数になっている)になることが示されている。つまり、PolyPCF=System F+fixpoint recursionと見なしていいってことかね。cataの場合、shortcut fusionは定義そのものなので、PolyPCFの組み込みのリストがforall x.x->(a->x->x)->xと"同型"と言えた時点で、ほとんど終わってる気もするが、そうでもないのかな。前者の論文で使われてるExtended typed lambda calculusも実質的に、PolyPCFといっしょな気がする。
しかし、いろいろややこしいなー