More Related Content More from Masahiro Sakai (20) 非正格関数に対して適用可能な融合変換8. 8
融合変換例
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]
14. 14
現実の言語における問題 (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の場合とで
場合分け
19. 19
2. 融合変換が可能な条件 (cont’d)
補題
関手 F: C→D と G: D→C が与えられたとき、
FG: D→D の始代数が存在することと、
GF: C→C の始代数が存在することは同値。
定理
任意のhに対してF(h)が正格 ⇒ Fの始代数が存在
この場合には始代数の性質に基づいた変換を行う
ことが可能
20. 20
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 の始代数とみなせる
23. 23
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))