什么是功能编程中的香蕉拆分和融合?


22

这些术语在我的大学课程中被提及。快速谷歌搜索使我找到了一些大学论文,但是我正在寻找一个简单的解释。


@jozefg:感谢您的文章链接。一个问题。在句子“从这个意义上讲,一个代数是一对对象C和一个映射FC→C。”中,C是否真的应该是对象,或者是类别?换句话说,我不确定F是否是类别中的函子,而F代数是否是由该函子引起的代数,也不确定F是否是从对象到其自身的特定箭头。
Giorgio 2015年

C是某个类别中的一个对象(例如CC),F是一个函子,CC -> CC因此它映射CC回自身。现在F CC -> CC只是类别中的普通箭头CC。因此,一个F代数是一个对象C : CC和一个箭头F C -> CCC
丹尼尔Gratzer

Answers:


4

尽管已经提供了2个答案,但我认为此处尚未解释“香蕉分割”。

确实在“使用香蕉,透镜,信封和铁丝网进行功能编程”,Erik Meijer Maarten Fokkinga,Ross Paterson,1991年中定义过;由于对Squiggol的大量使用,该文章(对我而言)难以阅读。但是,“关于折叠的通用性和表达性的教程,Graham Hutton,1999年”包含一个更易于解析的定义:

作为使用fold生成元组的简单第一个示例,请考虑用于计算数字列表的长度的函数sumlength

sumlength :: [Int] → (Int,Int)
sumlength xs = (sum xs, length xs)

通过使用前面给出的fold来简单地组合函数sumlength的定义,可以将函数sumlength重新定义为fold的单个应用程序,该函数从数字列表中生成一对数字:

sumlength = fold (λn (x, y) → (n + x, 1 + y)) (0, 0)

此定义比原始定义更有效,因为它仅对参数列表进行一次遍历,而不是两次单独遍历。从这个例子要概括,任何对应用于同一列表总是可以被组合以得到单一的应用程序的折叠产生的一对,通过吸引的所谓的“香蕉分裂”属性(梅耶尔,1992) 。此属性的奇怪名称源于以下事实:fold运算符有时使用类似于香蕉的方括号(| |)编写,而配对运算符有时称为split。因此,它们的组合可以称为香蕉分裂!


19

因此,这实际上是由Meijer和其他一些人称为“ 使用香蕉,镜片,信封和铁丝网进行功能编程 ”的论文所引用的,其基本思想是我们可以采用任何递归数据类型,例如

 data List = Cons Int List | Nil

我们可以将递归分解为类型变量

 data ListF a = Cons Int a | Nil

我附加的原因F是因为现在它是一个函子!它还允许我们模仿列表,但是要有所不同:要构建列表,我们必须嵌套列表类型

type ThreeList = ListF (ListF (ListF Void)))

要恢复我们的原始列表,我们需要将其无限嵌套。这将会给我们一个类型ListFF,其中

  ListF ListFF == ListFF

为此,请定义“定点类型”

  data Fix f = Fix {unfix :: f (Fix f)}
  type ListFF = Fix ListF

作为练习,您应该验证它是否满足上面的方程式。现在,我们终于可以定义什么是香蕉(变态)了!

  type ListAlg a = ListF a -> a

ListAlgs是“列表代数”的类型,我们可以定义一个特定的函数

  cata :: ListAlg a -> ListFF -> a
  cata f = f . fmap (cata f) . unfix

更进一步

  cata :: ListAlg a -> ListFF -> a
  cata :: (Either () (Int, a) -> a) -> ListFF -> a
  cata :: (() -> a) -> ((Int, a) -> a) -> ListFF -> a
  cata :: a -> (Int -> a -> a) -> ListFF -> a
  cata :: (Int -> a -> a) -> a -> [Int] -> a

看起来熟悉?cata与右折完全一样!

真正有趣的是,我们不仅可以使用列表,而且可以使用此“函子的固定点”定义的任何类型都具有a,cata并且为了容纳它们,我们只需要放松类型签名即可。

  cata :: (f a -> a) -> Fix f -> a

这实际上是从我写过的一个类别理论中得到启发的,但这是Haskell方面的实质。


2
值得一提的是,香蕉是原始纸张用来定义cata
jk的

7

尽管jozefg提供了答案,但我不确定它是否回答了问题。以下文件解释了“融合定律”:

关于折叠的通用性和表达性的教程,GRAHAM HUTTON,1999年

基本上,它说在某些情况下,您可以组合(“保险丝”)函数的组成并将其折叠为单个折叠,因此基本上

h·折叠gw =折叠fv

这种平等的条件是

hw = v
h(gxy)= fx(hy)

“香蕉分割”或“香蕉分割法”摘自该文章

香蕉,镜头,信封和铁丝网的功能编程,埃里克·迈耶·马腾·福金加,罗斯·帕特森,1991年

不幸的是,由于本文使用Bird-Meertens形式主义,因此很难解读,因此我无法说清楚它的开头或结尾。据我了解的“香蕉分割法”,它说,如果您对相同的论点有2折,则可以将它们合并为1折。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.