260 likes | 422 Views
非正格関数に対して適用可能な融合変換. 酒井 政裕 政策・メディア研究科 修士課程 2 年. 発表の流れ. 背景 純粋関数型言語 融合変換 現実の言語での問題 本研究の問題意識、アプローチ、結果 始代数が存在しない場合 始代数の存在条件 Haskell への適用 まとめ. 純粋関数型言語. 数学的な関数に基づく 入力だけから出力が決定される 副作用がないため、値が同じである式を自由に置き換え可能 特徴と利点 強い型付け , 高階関数 , 遅延評価 高いレベルでの柔軟性や信頼性を提供 代表的な言語 : Haskell.
E N D
非正格関数に対して適用可能な融合変換 酒井 政裕 政策・メディア研究科 修士課程2年
発表の流れ • 背景 • 純粋関数型言語 • 融合変換 • 現実の言語での問題 • 本研究の問題意識、アプローチ、結果 • 始代数が存在しない場合 • 始代数の存在条件 • Haskellへの適用 • まとめ
純粋関数型言語 • 数学的な関数に基づく • 入力だけから出力が決定される • 副作用がないため、値が同じである式を自由に置き換え可能 • 特徴と利点 • 強い型付け, 高階関数, 遅延評価 • 高いレベルでの柔軟性や信頼性を提供 • 代表的な言語: Haskell
Haskellプログラムの例 • 素数列挙 (エラトステネスのふるい) • sieve (p:xs) = [ x | x ← xs, x `mod` p ≠ 0 ] • primes = map head (iterate sieve [2..]) 図は日経ソフトウェア2006年6月号「Haskellによる関数プログラミング入門」より借用
純粋関数型言語 (cont’d) • 非常に宣言的・抽象的な記述が可能 • その分、ナイーブに実行すると性能が悪い • ⇒ 最適化が重要
融合変換 融合!!
融合変換 (cont’d) • 複数のパスからなるプログラム • わかりやすい • 中間データ構造が生成されるため、効率が悪い • これを単一のパスに変換 • 中間データ構造を生成しないことで空間効率を向上 • これまで離れていたコードが接することにより、更なる最適化が適用可能に ⇒ 時間効率も向上 • 主に(純粋)関数型言語で用いられる最適化
融合変換例 • double, square, map は以下のような関数 • double x = 2*x, square x = x*x • map f [x1, x2, x3, …] = [f x1, f x2, f x3, …] • 変換前: map square ∘ map double • [1, 2, 3] ↦ [2, 4, 6] ↦ [4, 16, 36] • 変換後: map (square∘double) • [1, 2, 3] ↦ [4, 16, 36]
融合変換の理論 • 変換には複数のプログラムの等価性が必要 • 背景となる理論 • 普遍性 (圏論) • 前提: データ型の普遍性= 条件を満たす関数がただ一つ存在する • 同じ条件を満たす関数は全て等しい • パラメトリシティ (多相ラムダ計算) • 以降では主に普遍性を扱う
データ型の普遍性 • 帰納的に定義されるデータ型 • 自然数, (有限)リスト, (有限)木 • 型上の演算 F の最小不動点 • 圏論的な定義 • 関手F: 型Xを型 F(X) へ、 関数 h:X→Y を F(h):F(X)→F(Y) へ写す • F代数: 型Xと関数φ: F(X)→X の組 (X, φ) • F始代数 (μF, in): • 任意の代数 (X, φ) への準同型がただ一つ存在する代数 • fold(φ): μF→X • 始代数の普遍性を利用して変換を行うことが出来る 普遍性
始代数の性質を用いる変換 • cata-Fusion (fold-Promotion)h∘φ = ψ∘F(h) ⇒ h∘fold(φ) = fold(ψ) 両辺とも (μF, in) から (Y, ψ) への準同型であり、 これはただ一つ存在する
始代数の性質を用いる他の変換 • short-cut deforestation • 忘却関手 |・|: Alg(F)→C の極限錘としての始代数の性質 • Θ:∀X.(FX→X)→(C→X)⇒ fold(φ)∘build(Θ) = Θ(φ) • hylomorphism • 始代数と終余代数が一致する場合 • fold(φ)∘unfold(ψ) = fix (λh. φ∘F(h)∘ψ)
現実の言語における問題 無限ループなどが書けてしまうため • 通常の数学の場合とは異なり、現実のプログラミング言語では停止しない計算 ⊥(ボトム) も考慮する必要がある • 関数 f が正格 ⇔ f(⊥)=⊥ • 純粋関数型言語では非正格な関数が存在 • e.g) ifte(b,t,e) = if b then t else e • データ型は一般に • 正格な関数に制限した場合には始代数 • 非正格な関数が存在する場合には始代数とは限らない
現実の言語における問題 (cont’d) • 以下のような、リスト上の関数を考える • f :: [Int] → [Int]f xs = 0 : (case xs of [] → [] (y:ys) → y : (f ys)) • f [1, 2, 3] = [0, 1, 0, 2, 0, 3, 0] • f ⊥ = (0 : ⊥) ≠ ⊥ なので f は非正格 • ⇒ リストの始代数としての性質が使えない • ⇒ 融合変換が適用可能か明らかではない 空リストの場合とconsの場合とで場合分け
本研究の問題意識 • 非正格な関数に対しては、融合変換を本当に適用できないのか? • もし適用可能だとしたら、どのような場合に適用可能なのか?
本研究の結果 • 多項式関手であっても始代数が存在しないことがあることを確認 • 始代数が存在するための条件を証明 • その条件をHaskellのデータ型に対して適用し、一般的なデータ型の多くに適用可能であることを示した • 入れ子データ型の場合にも同様であることを示した
1. 始代数が存在しない場合 • 問題 • 融合変換の幾つかの論文では、多項式関手の始代数が存在することを前提としている • 結果 • 多項式関手であっても始代数が存在しないことがあることを示した。(例: 恒等関手Id, 直積関手×) • 考察 • これらの論文は厳密性に問題がある • ではこれらの論文での変換はどこまで正しいのか?
2. 融合変換が可能な条件 • 問題点 • 一般にはデータ型は始代数にはならない • そのため融合変換が適用できない • 本研究のアプローチ • データ型が始代数になるための条件であり、十分多くのデータ型に適用可能なものを探す • その条件を満たすデータ型に対しては変換が可能になる
2. 融合変換が可能な条件 (cont’d) • 補題 • 関手 F: C→D と G: D→C が与えられたとき、FG: D→D の始代数が存在することと、GF: C→C の始代数が存在することは同値。 • 定理 • 任意のhに対してF(h)が正格 ⇒ Fの始代数が存在 • この場合には始代数の性質に基づいた変換を行うことが可能
3. Haskellへの適用 • 典型的な再帰的データ型 • data List a = Nil | Cons a (List a) • List A は F(X) = 1 + A×X の最小不動点 • 分離直和(separated sum)の形になっている • 任意の f, g に対して f+g は正格 • 任意の f に対して F(f) = id + id×f も正格 • List A は F の始代数とみなせる
3. Haskellへの適用 (cont’d) • 分離直和の形になっていない型 • 正格性フラグ (合体直和を使って解釈する必要) • 関数型 • それらを追跡し始代数として解釈可能か判定 • 始代数として解釈できない例: • data List’ a = Nil’ | Cons’ a !(List’ a)
3. Haskellでの簡単な変換例 • リスト上の非正格な関数の例f :: [Int] → [Int]f xs = 0 : (case xs of [] → [] (y:ys) → y : f ys) • f [1, 2, 3] ⇒ [0, 1, 0, 2, 0, 3, 0] • f ∘ map (+1) • 各要素に1を足したリストにfを適用 • これが変換可能であることがわかった
3. Haskellでの簡単な変換例 (cont’d) • F(X) = Maybe (A,X) とする • map (+1) を fold を使って表現 • map (+1) = fold phi where phi x = case x of Nothing → [] Just (a,r) → (a+1) : r • 以下のpsiが f∘phi = psi∘F(f) を満たす • psi x = 0 : (case x of Nothing → [] Just (a,r) → (a+1) : r) • 融合(cata-Fusion): f ∘ map (+1) = f ∘ fold phi = fold psi • fold psi を展開した再帰的定義: • f’ xs = 0 : (case xs of [] → [] (a:ys) → (a+1) : (f’ ys))
4. 入れ子データ型の場合 • 入れ子データ型 • 型引数が右辺で変化するデータ型 • e.g) 完全バランス木 • data PTree a = PZero a | PSucc (PTree (a,a)) • 単純な関手の不動点としては解釈できない • 高階の関手 H(F)(X) = X + F(X×X)の不動点として解釈 • 任意の関手Fに対して H(F)(h) が正格ならば、入れ子データ型は H の始代数として解釈可能
まとめ • 多項式関手であっても始代数が存在しない場合があることを示した。 • 始代数が存在するための条件で、十分適用範囲の広い条件を示した • Haskellのデータ型に対して適用した
今後の展望 • 始代数の普遍性だけでなく、パラメトリシティを対象に • パラメトリシティは普遍性よりも強い性質 • パラメトリシティから、データ型が始代数であることを示すことが出来る • 非正格な関数が存在する場合には、パラメトリシティも完全には成り立たず、特定の部分が正格な関数に制限される。 • パラメトリシティを対象とすることで、より多くの変換を対象に • 非正格な関数と正格な関数を区別し扱う体系への適用 • 直観主義論理と直観主義線形論理のモデルの間の随伴関手を用いたモデル • より精緻な結果が得られないか?