Function 无侧边褶皱的性质是什么?
Foldl和folr是FP和Haskell的两个非常重要的函数,但我从来没有听说过很多关于无辅助折叠的内容:Function 无侧边褶皱的性质是什么?,function,haskell,functional-programming,fold,Function,Haskell,Functional Programming,Fold,Foldl和folr是FP和Haskell的两个非常重要的函数,但我从来没有听说过很多关于无辅助折叠的内容: fold f [a,b,c,d] = (f (f a b) (f c d)) 也就是说,对二进制关联函数进行操作的折叠(因此应用程序的顺序无关紧要)。如果我没记错的话,这在数据库中非常常见,因为它可以并行化。因此,关于它,我问: 它像福尔德一样是通用的吗 像foldr一样,你能用它定义每个重要的函数吗 是否有类似于foldr/build和UNBOR/DISTRY的融合规则 为什么很少提
fold f [a,b,c,d] = (f (f a b) (f c d))
也就是说,对二进制关联函数进行操作的折叠(因此应用程序的顺序无关紧要)。如果我没记错的话,这在数据库中非常常见,因为它可以并行化。因此,关于它,我问:
您正在查找的函数是
Data.Foldable.foldMap
foldMap :: Data.Monoid.Monoid m => (a -> m) -> t a -> m
此函数同构于foldr
。作为证明,请注意foldMap
或foldr
中的一个是Foldable
的最小完整定义,这意味着可以根据另一个来编写。这肯定地回答了你的前两个问题
我不知道foldMap的具体融合规则,但我确信其中可能存在。至少,foldr融合规则应该在某种程度上适用
我不知道为什么很少提到
值得一提的一个考虑因素是,就列表而言,您不能总是充分利用这一优势。由于列表是由cons单元格构成的,进行树折叠意味着遍历列表的一半,然后向下递归每一半,然后再遍历一半,等等。与
foldl
或foldr
相比,这是大量额外的遍历。对于非列表结构,树形折叠可以更有效,甚至对于列表,也可以利用这一点。最近有一个关于这样的任务的好消息。这通常被认为是树约简,在并行计算中很重要,因为它体现了分治约简
首先,如果组合函数是非关联的,那么显然,foldl
、foldr
和“非辅助折叠”之间存在很大的差异,因此我们假设我们与关联操作组合。立即,所有折叠都可以用幺半群来表示
foldlm :: Monoid m => [m] -> m
foldlm = foldl mappend mempty
foldrm :: Monoid m => [m] -> m
foldrm = foldr mappend mempty
usfoldm :: Monoid m => [m] -> m
usfoldm = foldTree mappend mempty . buildTree
哪个更好地表示为foldMap::monoidm=>(a->m)->[a]->m
,默认情况下使用foldr
定义
foldMap f = foldr (mappend . f) mempty
如果给出了最后的提取步骤,这就足以产生树状的无边折叠,给定了在树状序列类型上定义的幺半群
,该序列类型控制元素-幺半群
的组合方式
data Tree a
singleton :: a -> Tree a
instance Monoid (Tree a) where ...
foldTree :: Monoid a => Tree a -> a
foldTree . foldMap singleton :: Monoid a => [a] -> a
最后,我们已经看到,我们可以从foldr
获得foldMap
,但是我们也可以从foldMap
获得foldr
newtype Endo a = Endo { appEndo :: a -> a }
instance Monoid (Endo a) where
mempty = id
mappend (Endo f) (Endo g) = Endo (f . g)
foldr f z as = appEndo (foldMap (Endo . f) as) z
一般来说,foldMap
被认为更原始,因为它允许底层的Monoid
选择其首选的折叠方法。这意味着我们可以自由地在每个数据类型级别上编写更高效或更并行的折叠,尽管正确地这样做仍然很有挑战性
值得注意的是,foldMap
抽象通常是作为Foldable
的一个实例方法发现的,这是一个非常流行但更新的Haskell类型类。它也被认为有点愚蠢,尽管它有实际用途,因为除此之外,Foldable
几乎没有什么有意义的定律
toList :: Foldable f => f a -> [a]
存在,这也让我们看到foldMap
的al性质,因为[a]
是通用的Monoid
,我们可以用foldr
来恢复它
foldMap f = foldr (mappend . f) mempty
为了进一步研究融合规则,阅读Gershom Bazerman提出的双类型类Buildable
,是很有价值的
最后,关于流行性,我认为这绝对是当前实例化可折叠
的首选方法,因为它允许更有效的Monoid
折叠(如果需要),但它肯定比foldl
和foldr
都要新,这可能会导致它的相对模糊性。可能更适合……我本想发布一个答案,但后来意识到我并不完全确定我在说什么。如果你还没有意识到,看看。它定义了一个类似于您描述的折叠
操作,只使用mappend
的隐式f
;接下来是关于如何定义任何数据类型的通用折叠。我认为Clojure的“还原器”在这里是相关的,因为Clojure促进有限seaences(数组样式序列,而不是cons/链表)的并行(多核)还原,这是一篇很棒的帖子,谢谢。你对可能的聚变定律有什么意见吗?没有完全考虑它,foldMap f。mapg==foldMap(f.g)
看起来很自然。还可以使用Gershom的Buildable class.infilling实现build/foldMap融合。谢谢