簡體   English   中英

catamorphisms的構成何時是一個變形?

[英]When is a composition of catamorphisms a catamorphism?

來自http://research.microsoft.com/en-us/um/people/emeijer/Papers/meijer94more.pdf的第3頁:

一般情況下,catamorphisms在組成下是封閉的

在什么條件下,catamorphisms構成了一個catamorphism? 更具體地說(假設我正確地理解了陳述):

假設我有兩個基函子FG並且每個都折疊: foldF :: (F a -> a) -> (μF -> a)foldG :: (G a -> a) -> (μG -> a)

現在假設我有兩個代數a :: F μG -> μGb :: 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 -> Afold1 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 gga -> 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都很樂意用lengthdoublemap f組成,因為它們在不查看子結果的情況下產生數據結構。 例如,在length的情況下,你可以用任何你想要的東西取代SuccZero ,並且你有新的變形。

  1. 如果第一個變形現象產生一個數據結構而沒有看到它的孩子會發生什么,那么兩個catamorphisms將組成一個catamorphism。

除此之外,事情變得更加復雜。 讓我們區分正常的構造函數參數和“遞歸參數”(我們將使用%符號標記)。 所以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) .. ,那也可以。

從這里開始,我希望規則會變得更加混亂。

Catamorphisms將數據結構解構為結果值。 所以,一般來說,當你應用一個變形時,結果是完全不同的,你不能對它應用另一個變形。

例如,對[Int]所有元素求和的函數是一個catamorphism,但結果是Int 沒有辦法如何應用另一個catamorphism。

但是,一些特殊的catamorphisms會創建與輸入相同類型的結果。 一個這樣的例子是map f (對於某些給定的函數f )。 雖然它解構了原始結構,但它也會創建一個新列表作為結果。 (實際上, map f既可以看作是一種變形也可以看作是一種變形現象 。)因此,如果你有這樣一類特殊的變形,你可以將它們組合起來。

如果我們考慮語義等價,當第一個是一個同性戀時,兩個同態的組成是一個變形:

cata1 . hylo1 = cata2

例如(Haskell):

sum . map (^2) = foldl' (\x y -> x + y^2) 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM