簡體   English   中英

在一個變構中組成f-代數的規則是什么?

[英]What are the rules to compose f-algebras in a catamorphism

這里有一些簡單的F代數用於列表。 它們使用遞歸方案庫中的cata函數。

import Data.Functor.Foldable

algFilterSmall :: ListF Int [Int] -> [Int]
algFilterSmall Nil = [] 
algFilterSmall (Cons x xs) = if x >= 10 then (x:xs) else xs

algFilterBig :: ListF Int [Int] -> [Int]
algFilterBig Nil = [] 
algFilterBig (Cons x xs) = if x < 100 then (x:xs) else xs

algDouble :: ListF Int [Int] -> [Int]
algDouble Nil = [] 
algDouble (Cons x xs) = 2*x : xs

algTripple :: ListF Int [Int] -> [Int]
algTripple Nil = [] 
algTripple (Cons x xs) = 3*x : xs

現在我把它們組成:

doubleAndTripple :: [Int] -> [Int]
doubleAndTripple = cata $ algTripple . project . algDouble
-- >>> doubleAndTripple [200,300,20,30,2,3]
-- [1200,1800,120,180,12,18]

doubleAndTriple按預期工作。 兩個代數都是結構保留的 ,它們不會改變列表的長度,因此cata可以將兩個代數應用於列表的每個項目。

下一個是過濾和雙重:

filterAndDouble :: [Int] -> [Int] 
filterAndDouble = cata $ algDouble . project . algFilterBig
-- >>> filterAndDouble [200,300,20,30,2,3]
-- [160,60,4,6]

它無法正常工作。 我認為這是因為algFilterBig不是結構保留。

現在是最后一個例子:

filterBoth :: [Int] -> [Int] 
filterBoth = cata $ algFilterSmall . project . algFilterBig 
-- >>> filterBoth [200,300,20,30,2,3]
-- [20,30]

這兩個代數都不是結構保留,但這個例子是有效的。

組成f-algebras的確切規則是什么?

“保持代數的結構”可以形式化為自然變換(可以在不同的算子之間)。

inList :: ListF a [a] -> [a]
inList Nil = []
inList (Cons a as) = a : as

ntDouble, ntTriple :: forall a. ListF Int a -> ListF Int a
algDouble = inList . ntDouble
algTriple = inList . ntTriple

然后,對於任何代數f和自然變換n

cata (f . inList . n) = cata f . cata n

doubleAndTriple示例是f = algTriplen = ntDouble

這並不容易推廣到更大類的代數。

我認為濾波器的情況更容易看到沒有類別,因為filter是半群同態的事實: filter p . filter q = filter (liftA2 (&&) pq) filter p . filter q = filter (liftA2 (&&) pq)


我在類似濾波器的代數上尋找一個通用但充分條件的“分配律”。 縮寫為afs = algFilterSmallafb = algFilterBig 我們向后推理,找到一個充分條件:

cata (afs . project . afb) = cata afs . cata afb  -- Equation (0)

根據catamorphism的定義, z = cata (afs . project . afb)是這個等式的唯一解(一個偽裝的交換圖):

z . inList = afs . project . afb . fmap z

用前一個等式的RHS代替z

cata afs . cata afb . inList = afs . project . afb . fmap (cata afs . cata afb)
-- (1), equivalent to (0)
  • 在LHS上,我們將cata的定義cata為Haskell函數, cata afb = afb . fmap (cata afb) . project cata afb = afb . fmap (cata afb) . project cata afb = afb . fmap (cata afb) . project ,並簡化project . inList = id project . inList = id ;

  • 在RHS上,我們應用了一個fmap (f . g) = fmap f . fmap g子法fmap (f . g) = fmap f . fmap g fmap (f . g) = fmap f . fmap g

這會產生:

cata afs . afb . fmap (cata afb) = afs . project . afb . fmap (cata afs) . fmap (cata afb)
-- (2), equivalent to (1)

我們“縮小”最后一個因素fmap (cata afb) (記住我們向后推理):

cata afs . afb = afs . project . afb . fmap (cata afs)  -- (3), implies (2)

這是我能想到的最簡單的一個。

暫無
暫無

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

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