[英]Haskell fold function on tree
我正在努力与这个例子:
编写一个将函数折叠到树上的折叠函数。 (因此,例如,
fold min t
将在树中找到最小的元素。)fold :: (a -> a -> a) -> Tree -> a
*这是我的剧本
data Tree = Leaf Int
| Fork Tree Int Tree
deriving Show
t0 = Leaf 0
t1 = Fork (Fork (Leaf 1) 2 (Leaf 3)) 4 (Fork (Leaf 5) 6 (Leaf 7))
t2 = Fork (Fork (Fork (Leaf 1) 2 (Leaf 3)) 4 (Leaf 5)) 6 (Leaf 7)
fold :: (a -> a -> a) -> Tree -> a
fold f v (Leaf n) = v
fold f v (Fork l n r) = f (Folk l) (fold f v (Fork r))
感谢您的任何建议
有一件事,在函数fold
的签名中,您要说它将接收2个参数,一个二进制函数(可以是一个运算符),一个Tree并返回a
。 现在,在定义中,您有3个参数f
,一些v
和Tree
的构造函数。
解决方案可能是这样的:
fold :: (Int -> Int -> Int) -> Tree -> Int
fold f (Leaf n) = n
fold f (Fork l n r) = f n m
where
m = f (fold f l) (fold f r)
您需要说您正在返回一个Int
因为您的Tree
拥有Int
。
编辑
此外,您可以使用刚性类型变量来重新定义数据。
data Tree a = Leaf a
| Fork (Tree a) a (Tree a)
deriving Show
fold :: (a -> a -> a) -> Tree a -> a
fold f (Leaf n) = n
fold f (Fork l n r) = f n m
where
m = f (fold f l) (fold f r)
我建议您阅读Data.Foldable的文档。 他们有一个使用Tree
数据类型的示例。
折痕可以机械地衍生自任何类型。 这是foldMaybe
:
data Maybe a = Nothing | Just a
foldMaybe :: r -> (a -> r) -> Maybe a -> r
foldMaybe _ k (Just a) = k a
foldMaybe d _ Nothing = d
“折叠”数据类型意味着我们将提供一种将该类型的每种可能的构造函数组合为最终类型r
。 在这里, Maybe
有两个构造函数:一个构造函数具有0个值,另一个构造函数具有单个a
类型a
值。 因此,要折叠它,我们需要为Nothing
情况提供一个值,并提供一个将Just a
转换为r
。
让我们看一下list
,看看foldr
是如何从中派生的。
data List a = Nil | Cons a (List a)
[1] [2 3 4] [4]
foldList :: r -> (a -> r -> r) -> List a -> r
Nil
时要使用的值。 Cons
情况的功能。 由于Cons
的第一个值是a
,因此该函数必须取a
。 Cons
取的第二个值是a (List a)
,为什么我们取r
? 好! 我们正在定义一个可以使用List a
并返回r
,因此我们将在与当前节点合并之前处理列表的其余部分。 r
。 实现是什么样的?
foldList nil cons list = case list of
Nil -> nil
Cons a as -> cons a (foldList nil cons list)
因此,我们将所有构造函数替换为对应的“析构函数”,并在必要时重复进行。
对于树木:
data Tree = Leaf Int | Fork Tree Int Tree
我们有两个构造函数:一个构造函数使用一个Int
,另一个构造函数使用三个参数Tree
, Int
和Tree
。
让我们来写类型签名!
treeFold :: LeafCase r -> ForkCase r -> r
嗯,但是我们必须定义LeafCase
:
type LeafCase r = Int -> r
由于Leaf
使用单个Int作为参数,因此这就是该函数的类型。
type ForkCase r = r -> Int -> r -> r
同样,我们用r
类型参数替换了Fork
中Tree
所有递归用法。 因此,我们的完整功能如下所示:
foldTree :: (Int -> r) -> (r -> Int -> r -> r) -> Tree -> r
实施可能会像这样开始:
foldTree leaf fork tree = case tree of
Leaf i -> error "halp"
Fork l i r -> error "complete me?"
我有信心您可以填补这些空缺:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.