Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 无侧边褶皱的性质是什么?_Function_Haskell_Functional Programming_Fold - Fatal编程技术网

Function 无侧边褶皱的性质是什么?

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的融合规则 为什么很少提

Foldl和folr是FP和Haskell的两个非常重要的函数,但我从来没有听说过很多关于无辅助折叠的内容:

fold f [a,b,c,d] = (f (f a b) (f c d))
也就是说,对二进制关联函数进行操作的折叠(因此应用程序的顺序无关紧要)。如果我没记错的话,这在数据库中非常常见,因为它可以并行化。因此,关于它,我问:

  • 它像福尔德一样是通用的吗
  • 像foldr一样,你能用它定义每个重要的函数吗
  • 是否有类似于foldr/build和UNBOR/DISTRY的融合规则
  • 为什么很少提及
  • 有什么值得一提的考虑吗

  • 您正在查找的函数是
    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融合。谢谢