简体   繁体   English

在一个变构中组成f-代数的规则是什么?

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

Here are some simple F-algebras for lists. 这里有一些简单的F代数用于列表。 They work with the cata function from the recursion-schemes library. 它们使用递归方案库中的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

Now I compose them: 现在我把它们组成:

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

doubleAndTriple works as expected. doubleAndTriple按预期工作。 Both algebras are structure preserving , they don't change the length of the list, so cata can apply both algebras to every item of the list. 两个代数都是结构保留的 ,它们不会改变列表的长度,因此cata可以将两个代数应用于列表的每个项目。

Next one is filter and double: 下一个是过滤和双重:

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

It doesn't work properly. 它无法正常工作。 I assume it's because algFilterBig is not structure preserving. 我认为这是因为algFilterBig不是结构保留。

Now the last example: 现在是最后一个例子:

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

Here both algebras are not structure preserving, but this example is working. 这两个代数都不是结构保留,但这个例子是有效的。

What are the exact rules for composing f-algebras? 组成f-algebras的确切规则是什么?

"Structure preserving algebras" can be formalized as natural transformations (that can be between different functors). “保持代数的结构”可以形式化为自然变换(可以在不同的算子之间)。

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

Then, for any algebra f and natural transformation n , 然后,对于任何代数f和自然变换n

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

The doubleAndTriple example is an instance of that for f = algTriple and n = ntDouble . doubleAndTriple示例是f = algTriplen = ntDouble

This doesn't easily generalize to larger classes of algebras. 这并不容易推广到更大类的代数。

I think the case of filter is easier to see without categories, as a consequence of the fact that filter is a semigroup homomorphism: filter p . filter q = filter (liftA2 (&&) pq) 我认为滤波器的情况更容易看到没有类别,因为filter是半群同态的事实: filter p . filter q = filter (liftA2 (&&) pq) filter p . filter q = filter (liftA2 (&&) pq) . filter p . filter q = filter (liftA2 (&&) pq)


I searched for a general but sufficient condition for a "distributive law" on filter-like algebras. 我在类似滤波器的代数上寻找一个通用但充分条件的“分配律”。 Abbreviate a bit afs = algFilterSmall , afb = algFilterBig . 缩写为afs = algFilterSmallafb = algFilterBig We reason backwards, to find a sufficient condition for: 我们向后推理,找到一个充分条件:

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

By definition of a catamorphism, z = cata (afs . project . afb) is the unique solution to this equation (a disguised commutative diagram): 根据catamorphism的定义, z = cata (afs . project . afb)是这个等式的唯一解(一个伪装的交换图):

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

Substitute z with the RHS of the previous equation: 用前一个等式的RHS代替z

cata afs . cata afb . inList = afs . project . afb . fmap (cata afs . cata afb)
-- (1), equivalent to (0)
  • On the LHS, we apply the definition of cata as a Haskell function, cata afb = afb . fmap (cata afb) . project 在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 , and simplify with project . inList = id cata afb = afb . fmap (cata afb) . project ,并简化project . inList = id project . inList = id ; project . inList = id ;

  • on the RHS, we apply a functor law fmap (f . g) = fmap f . fmap g 在RHS上,我们应用了一个fmap (f . g) = fmap f . fmap g子法fmap (f . g) = fmap f . fmap g fmap (f . g) = fmap f . fmap g . fmap (f . g) = fmap f . fmap g

This yields: 这会产生:

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

We "cosimplify" away the last factor fmap (cata afb) (remember that we are reasoning backwards): 我们“缩小”最后一个因素fmap (cata afb) (记住我们向后推理):

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

This is the simplest one I could come up with. 这是我能想到的最简单的一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM