折叠ITree

时间:2014-11-17 03:10:56

标签: haskell

鉴于以下ITree,来自Typeclassopedia

data ITree a = Leaf (Int -> a) | Node [ITree a]

foldTree的正确签名是什么 - 折叠整个树?

我的错误尝试是编译:

foldTree :: (a -> [b] -> b) -> ITree a -> b
foldTree f (Leaf x)  = f x []
foldTree f (Node xs) = f _ $ map (foldTree f) xs 

然而,传递Leaf x案例的空列表对我来说似乎很奇怪。

此外,在Node的第二个模式匹配中,我不知道如何应用a,因为我没有应用Node [ITree a] {{1}} }。

1 个答案:

答案 0 :(得分:2)

我正试图找出foldTree签名背后的原因。

根据Foldable section of the Typeclassopedia,通用折叠操作具有以下签名之一:

class Foldable t where
  fold    :: Monoid m => t m -> m
  foldMap :: Monoid m => (a -> m) -> t a -> m

  foldr   :: (a -> b -> b) -> b -> t a -> b
  foldl   :: (a -> b -> a) -> a -> t b -> a
  foldr1  :: (a -> a -> a) -> t a -> a
  foldl1  :: (a -> a -> a) -> t a -> a

它还说其他人可能来自foldfoldMap

让我们试着找出foldMap的{​​{1}}内容。

来自签名:

ITree a

很明显,创建foldMap :: Monoid m => (a -> m) -> ITree a -> m foldMap f (Leaf x) = ??? 的唯一方法是将合并函数m应用于某些f。但是从a获取a的唯一方法是将Leaf x(这是一个函数)应用于某些x,如下所示:

Int

这里我们选择在0处评估foldMap f (Leaf x) = f (x 0) ,但任何整数常量都可以。

对于x案例,这似乎是唯一的可能性:

Node

也就是说,我们折叠了所有树,为我们提供了foldMap f (Node ts) = mconcat [ foldMap f t | t <- ts ] 值列表,然后使用m将其缩减为单个mconcat

总而言之,m定义所发生的一切是:

  1. foldMap
  2. 开头
  3. 以某个常量评估所有叶节点。
  4. 现在你有一个传统的价值树。
  5. 在该树上执行标准折叠。