[英]When is a composition of catamorphisms a catamorphism?
來自http://research.microsoft.com/en-us/um/people/emeijer/Papers/meijer94more.pdf的第3頁:
一般情況下,catamorphisms在組成下是封閉的
在什么條件下,catamorphisms構成了一個catamorphism? 更具體地說(假設我正確地理解了陳述):
假設我有兩個基函子F
和G
並且每個都折疊: foldF :: (F a -> a) -> (μF -> a)
和foldG :: (G a -> a) -> (μG -> a)
。
現在假設我有兩個代數a :: F μG -> μG
和b :: GX -> X
何時是組合物(foldG b) . (foldF a) :: μF -> X
(foldG b) . (foldF a) :: μF -> X
a catamorphism?
編輯:我有一個猜測,基於dblhelix的擴展答案: outG . a :: F μG -> G μG
outG . a :: F μG -> G μG
必須是某些自然變換η :: F a -> G a
μG
分量。 我不知道這是否正確。 ( 編輯2:正如科拉指出的那樣,這已足夠,但並非必要。)
編輯3: Wask Thornton在Haskell-Cafe上補充道:“如果你有正確的分配屬性(正如科拉所建議的那樣),那么事情就會適用於特定情況。但是,擁有正確的分配屬性通常相當於在一些適當相關的類別中進行自然變換;因此,只是將問題推遲到是否存在適當相關的類別,以及我們是否可以將“適當相關”的含義形式化。“
何時是組合物(fold2g)。 (fold1 f)::μF1 - >一個變形?
當存在F1
代數h :: F1 A -> A
, fold1 h = fold2 g . fold1 f
fold1 h = fold2 g . fold1 f
。
要看到catamorphisms一般不在組合下關閉,請考慮以下類型級別定點,代數和變形的一般定義:
newtype Fix f = In {out :: f (Fix f)}
type Algebra f a = f a -> a
cata :: Functor f => Algebra f a -> Fix f -> a
cata phi = phi . fmap (cata phi) . out
對於catamorphisms組成我們需要
algcomp :: Algebra f (Fix g) -> Algebra g a -> Algebra f a
現在嘗試編寫這個函數。 它需要兩個函數作為參數(類型f (Fix g) -> Fix g
和ga -> a
)和類型fa
的值,它需要生成類型a
的值。 你會怎么做? 為了生產類型的值a
你唯一的希望是應用型的功能ga -> a
,但后來我們被卡住:我們也沒辦法把類型的值fa
到類型的值ga
,有我們?
我不確定這是否對你的目的有用,但是一個條件的例子就是我們可以從第二個cata的結果到第二個仿函數的固定點有一個態射:
algcomp' :: (Functor f, Functor g) =>
(a -> Fix g) -> Algebra f (Fix g) -> Algebra g a -> Algebra f a
algcomp' h phi phi' = cata phi' . phi . fmap h
(免責聲明:這超出了我的專業領域。我相信我是正確的(在不同的地方提供警告),但是......自己驗證。)
可以將catamorphism視為將數據類型的構造函數替換為其他函數的函數。
(在此示例中,我將使用以下數據類型:
data [a] = [] | a : [a]
data BinTree a = Leaf a | Branch (BinTree a) (BinTree a)
data Nat = Zero | Succ Nat
)
例如:
length :: [a] -> Nat
length = catamorphism
[] -> 0
(_:) -> (1+)
(可悲的是,在Haskell中沒有catamorphism {..}
語法(我在Pola中看到類似的東西)。我一直想為它寫一個quasiquoter。)
那么, length [1,2,3]
是多少length [1,2,3]
?
length [1,2,3]
length (1 : 2 : 3 : [])
length (1: 2: 3: [])
1+ (1+ (1+ (0 )))
3
也就是說,由於后來會變得明顯的原因,將它定義為平凡等價的更好:
length :: [a] -> Nat
length = catamorphism
[] -> Zero
(_:) -> Succ
讓我們再考慮一些示例性的catamorphisms:
map :: (a -> b) -> [a] -> b
map f = catamorphism
[] -> []
(a:) -> (f a :)
binTreeDepth :: Tree a -> Nat
binTreeDepth = catamorphism
Leaf _ -> 0
Branch -> \a b -> 1 + max a b
binTreeRightDepth :: Tree a -> Nat
binTreeRightDepth = catamorphism
Leaf _ -> 0
Branch -> \a b -> 1 + b
binTreeLeaves :: Tree a -> Nat
binTreeLeaves = catamorphism
Leaf _ -> 1
Branch -> (+)
double :: Nat -> Nat
double = catamorphism
Succ -> Succ . Succ
Zero -> Zero
其中許多可以很好地組成形成新的catamorphisms。 例如:
double . length . map f = catamorphism
[] -> Zero
(a:) -> Succ . Succ
double . binTreeRightDepth = catamorphism
Leaf a -> Zero
Branch -> \a b -> Succ (Succ b)
double . binTreeDepth
double . binTreeDepth
也有效,但在某種意義上它幾乎是一個奇跡。
double . binTreeDepth = catamorphism
Leaf a -> Zero
Branch -> \a b -> Succ (Succ (max a b))
這只能起作用,因為double
分布超過max
...這是純粹的巧合。 (對於double . binTreeLeaves
也是如此。)如果我們用一些不能很好玩的東西替換max
加倍...好吧,讓我們自己定義一個新朋友(與其他朋友不相處) 。 對於double
不分配的二元運算符,我們將使用(*)
。
binTreeProdSize :: Tree a -> Nat
binTreeProdSize = catamorphism
Leaf _ -> 0
Branch -> \a b -> 1 + a*b
讓我們嘗試為兩個組合構建兩個構造的充分條件。 很明顯,任何catamorphism都很樂意用length
, double
和map f
組成,因為它們在不查看子結果的情況下產生數據結構。 例如,在length
的情況下,你可以用任何你想要的東西取代Succ
和Zero
,並且你有新的變形。
除此之外,事情變得更加復雜。 讓我們區分正常的構造函數參數和“遞歸參數”(我們將使用%符號標記)。 所以Leaf a
沒有遞歸參數,但Branch %a %b
確實如此。 讓我們使用構造函數的“遞歸固定”一詞來指代它具有的遞歸參數的數量。 (我已經完成了這兩個術語!我不知道什么是合適的術語,如果有的話!在其他地方使用它們時要小心!)
如果第一個catamorphism映射到零遞歸固定構造函數,一切都很好!
a | b | cata(b.a)
===============================|=========================|================
F a %b %c .. -> Z | Z -> G a b .. | True
如果我們將孩子直接映射到一個新的構造函數,我們也很好。
a | b | cata(b.a)
===============================|=========================|=================
F a %b %c .. -> H %c %d .. | H %a %b -> G a b .. | True
如果我們映射到一個遞歸固定一個構造函數...
a | b | cata(b.a)
===============================|=========================|=================
F a %b %c .. -> A (f %b %c..) | A %a -> B (g %a) | Implied by g
| | distributes over f
但它不是iff。 例如,如果存在g1
g2
使得g (fa b..) = f (g1 a) (g2 b) ..
,那也可以。
從這里開始,我希望規則會變得更加混亂。
如果我們考慮語義等價,當第一個是一個同性戀時,兩個同態的組成是一個變形:
cata1 . hylo1 = cata2
例如(Haskell):
sum . map (^2) = foldl' (\x y -> x + y^2) 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.