haskell basecase在平衡折叠

时间:2015-10-28 09:23:51

标签: haskell

Haskell中存在不同类型的折叠,例如foldlfoldr。 我读到了以下平衡折叠:

balanced_fold::(e->e->e)->e->[e]->e
balanced_fold _ b [] =b
balanced_fold f b l@(_:_:_)=
   let 
      len= length l
      (half1,half2)=
        divide_list (div len 2) l
      value1=balanced_fold f b half1
      value2=balanced_fold f b half2
   in 
      f value1 value2
divide_list :: Int-> [a]->([a],[a])
divide_list _ [] =([],[])
divide_list n (x:xs)
     | n==0 =([],x:xs)
     | otherwise =
         let (half1,half2)=
             divide_list (n-1) xs
         in 
             (x:half1, half2)

根据定义,当列表只包含一个元素[x]时,输出将为x

我的问题是:当一个列表只包含一个元素时,我们不需要使用基值来处理这个元素吗?

我们知道,foldrfoldl确实使用基值来处理列表中的元素,即使只有一个元素。

foldl::(v->e->v)->v->[e]->v
foldl _ base [] =base
foldl f base (x:xs)=
     let newbase =f base x in
     foldl f newbase xs

1 个答案:

答案 0 :(得分:3)

我希望这能回答你的问题:

首先让我们修复你的功能:

balanced_fold :: (e -> e -> e) -> e -> [e] -> e
balanced_fold _ b []  = b
balanced_fold f b [a] = f b a
balanced_fold f b l =
   let len= length l
       (half1,half2)= divide_list (div len 2) l
       value1=balanced_fold f b half1
       value2=balanced_fold f b half2
   in f value1 value2

你可以看到我添加了一个处理长度1(缺失的部分)列表的案例 - 我希望你现在看到基础案例的位置

你所拥有的问题是,它只有一个元素的列表没有匹配的情况 - 即使你要删除(_:_:_)(你真的不需要)你会结束在divide_list始终为您提供类似([],[x])并且[x]会在同一案例中递归 - 的情况下 - 这就是为什么您需要额外案例来处理这种情况的原因

这是一个快速测试会话,看它是否有效:

λ> balanced_fold (+) 0 []
0
λ> balanced_fold (+) 0 [1]
1
λ> balanced_fold (+) 0 [1..4]
10
λ> balanced_fold (+) 0 [1..5]
15
我觉得

似乎没问题

也许很高兴知道

注意当你的操作是 associative 并且你有某种 base / 中性元素时,这一切只能起作用(对于这个操作) )。

所有这些已经有一个课程Monoid,所以你也可以这样写:

import Data.Monoid

balanced_fold :: Monoid e => [e] -> e
balanced_fold []  = mempty
balanced_fold [a] = a
balanced_fold l =
   let len           = length l
       (half1,half2) = divide_list (div len 2) l
       value1        = balanced_fold half1
       value2        = balanced_fold half2
   in value1 `mappend ` value2

看到它只是

  • f现在是mappend
  • b只是mempty

现在申请这个例子有点难看:

λ> balanced_fold (map Sum [1..4])
Sum {getSum = 10}

但这只是因为数字可能有多个monoid。