我是Haskell的初学者。在这里,我试图理解一个Haskell函数,该函数计算树的最大分支度。
以下是数据类型:
data Tree a = Node a [Tree a] deriving (Show)
leaf :: a -> Tree a
leaf a = Node a []
这里是实现:
maxBranching :: Tree a -> Int
maxBranching (Node _ ts) = let localBranching = length ts in
max localBranching (maxBranchingOfSubtrees ts)
where maxBranchingOfSubtrees :: [Tree a] -> Int
maxBranchingOfSubtrees [] = 0
maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)
这是示例输入:
Node 2 [leaf 7, Node 3 [leaf 0], Node 1 [leaf 3, leaf 2]]
我不明白这个表达:
maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)
max
是如何将第一个元素与列表的其余部分进行比较的?每次迭代后,它在哪里更新最大值?如果我看到何时将列表的第一个元素设为Leaf 7
作为maxBranching x
传递,则没有这种情况,它如何返回列表的第一个元素的长度,然后如何{ {1}}处理列表的其余部分?而起初maxBranchingOfSubtress
包含列表localBranching
?任何形式的详细帮助将不胜感激。
答案 0 :(得分:1)
您问题的简单答案是,所有类型都完美地结合在一起。
如果为(x:xs) :: [Tree a]
,则为x :: Tree a
和xs :: [Tree a]
,因为(:) :: a -> [a] -> [a]
或此处为(:) :: Tree a -> [Tree a] -> [Tree a]
:
(:) :: Tree a -> [Tree a] -> [Tree a]
( x : xs ) :: [Tree a]
----------------------------------
x :: Tree a xs :: [Tree a]
根据函数的签名
maxBranching :: Tree a -> Int
x :: Tree a
---------------------------------
(maxBranching x) :: Int
和
maxBranchingOfSubtrees :: [Tree a] -> Int
xs :: [Tree a]
---------------------------------------------
(maxBranchingOfSubtrees xs) :: Int
所以我们确实可以拥有
max :: Int -> Int -> Int
max (maxBranching x) (maxBranchingOfSubtrees xs) :: Int
因此max
不是 “将第一个元素与列表的其余部分进行比较”。而是将第一个元素上的计算maxBranching
的结果与列表其余部分上的计算maxBranchingOfSubtrees
的结果进行比较。
最后一点,您问如何知道如何做到这一点?只需使用相同的maxBranchingOfSubtrees
配方即可。换句话说,通过做同样的事情 -但这一次的事情比以前更“小”。列表的尾部是列表的 part 。
因此最终,此递归将会顺利进行,我们将得到答案-如果树的列表不是无限的,那就是。因此,这假设分支因子不是无限的。
因此,这将找到节点子树的最大分支因子,然后将其与该节点的分支因子进行比较,以产生总体最大值。
另一种看法是
maxBranchingOfSubtrees [] = 0
maxBranchingOfSubtrees (x:xs) = max (maxBranching x) (maxBranchingOfSubtrees xs)
= (max . maxBranching) x (maxBranchingOfSubtrees xs)
适合foldr
模式,
maxBranchingOfSubtrees = foldr (max . maxBranching) 0
这符合映射模式
maxBranchingOfSubtrees = foldr max 0 . map maxBranching
并且有一个内置函数,
maxBranchingOfSubtrees = maximum . (0 :) . map maxBranching
然后将其替换为主要功能
maxBranching :: Tree a -> Int
maxBranching (Node _ ts) = max (length ts) (maxBranchingOfSubtrees ts)
= max (length ts) (maximum (0 : map maxBranching ts))
= maximum (length ts : map maxBranching ts)
使用高阶函数表示相同的算法,而不是手动递归循环。