我真的很喜欢这个repmin
问题:
写下
repmin :: Tree Int -> Tree Int
,它在一次通过中将树中的所有数字替换为它们的最小值。
如果我在 python 中编写这样的东西,我会通过引用传递值(假设单元素列表而不是数字就足够了):
def repmin(tree, wrapped_min_link=None):
x, subforest = tree
if wrapped_min_link is None:
wrapped_min_link = [x]
else:
[m] = wrapped_min_link
wrapped_min_link = [min(m, x)]
n = len(subforest)
subforest_min = [None] * n
for i in range(n):
if subforest[i]:
subforest_min[i] = repmin(subforest[i], wrapped_min_link)
return (wrapped_min_link, subforest_min)
在我看来,这似乎是一种合适的方式来围绕 Haskell 中的打结解决方案(我从 为玫瑰树Data.Tree
写了这个):
copyRose :: Tree Int -> Int -> (Tree Int, Int)
copyRose (Node x []) m = (Node m [], x)
copyRose (Node x fo) m =
let
unzipIdMinimum =
foldr (\ ~(a, b) ~(as, bmin) -> (a:as, b `min` bmin)) ([], maxBound :: Int)
(fo', y) = unzipIdMinimum . map (flip copyRose m) $ fo
in (Node m fo', x `min` y)
repmin :: Tree Int -> Tree Int
repmin = (loop . uncurry) copyRose
然而,我认为解决方案的工作方式非常不同。以下是我对后一种的理解:
让我们重写loop
一下(->)
:
loop f b = let cd = f (b, snd cd) in fst cd
我认为它与loop
for(->)
的工作相似,因为snd
它给出了与let
.
因此,当repmin
遍历树时,它是:
- 在树中建立最小值,作为该对的第二个元素返回。
snd $ copyRose (tree, m)
在每个节点中留下。
因此,当遍历结束时,程序知道snd $ copyRose (tree, m)
(即树中的最小值)的值,并且能够在计算树的某个节点时显示它。
我repmin
在 Haskell 中理解正确吗?