repmin如何在Haskell中的树中放置值?
我非常喜欢repmin如何在Haskell中的树中放置值?,haskell,tree,fixpoint-combinators,tying-the-knot,Haskell,Tree,Fixpoint Combinators,Tying The Knot,我非常喜欢repmin问题: 写下repmin::Tree Int->Tree Int,在一次传递中用最小值替换树中的所有数字 如果我在python中编写类似的东西,我会使用它们的引用来传递值(假设一个元素列表而不是数字就足够了): def repmin(树,wrapped_min_link=None): x、 子休息=树 如果“包装的\u最小\u链接”为“无”: 包装的\u最小\u链接=[x] 其他: [m] =已包装的\u最小\u链接 包裹的最小链接=[min(m,x)] n=len(子休息
repmin
问题:
写下repmin::Tree Int->Tree Int
,在一次传递中用最小值替换树中的所有数字
如果我在python中编写类似的东西,我会使用它们的引用来传递值(假设一个元素列表而不是数字就足够了):
def repmin(树,wrapped_min_link=None):
x、 子休息=树
如果“包装的\u最小\u链接”为“无”:
包装的\u最小\u链接=[x]
其他:
[m] =已包装的\u最小\u链接
包裹的最小链接=[min(m,x)]
n=len(子休息)
子REST_min=[None]*n
对于范围(n)中的i:
如果子休息[i]:
子REST\u min[i]=repmin(子REST[i],包装的\u min\u链接)
返回(已包装的\u min\u链接,子休息\u min)
在我看来,这似乎是一种合适的方法,可以让人在Haskell的打结解决方案中保持清醒(我写这篇文章是为了:
copyRose::Tree Int->Int->(Tree Int,Int)
copyRose(节点x[])m=(节点m[],x)
copyRose(节点x fo)m=
让
unzipIdMinimum=
foldr(\~(a,b)~(as,bmin)->(a:as,b`min`bmin))([],maxBound::Int)
(fo',y)=最小值。地图(翻页复制m)$fo
in(节点m fo',x`min`y)
repmin::Tree Int->Tree Int
repmin=(loop.uncurry)copyRose
然而,我认为解决方案的效果非常不同。以下是我对后者的理解:
让我们重写一下:
我认为它的工作原理与snd
的工作原理类似,snd的惰性程度与let
中的模式匹配相同
因此,当repmin
遍历树时,它是:
- 在树中建立最小值,作为对的第二个元素返回
- 在每个节点中留下
snd$copyRose(树,m)
snd$copyRose(tree,m)
(即树中的最小值)的值,并且能够在计算树的某个节点时显示该值
我是否正确理解Haskell中的
repmin
?这与其说是一个答案,不如说是一个扩展注释,但我并不认为您的实现是一个简单的过程。它看起来像是遍历了一次树,生成了一个新的、延迟生成的树和全局最小值,但实际上它生成了一个延迟生成的树和一个巨大的thunks树,最终将计算最小值。为了避免这种情况,您可以通过急切地生成树来更接近Python代码,同时跟踪最小值
您会注意到,我已经将类型从Int
概括为任意Ord
类型。您还将注意到,我使用了不同的类型变量来引用给定树中元素的类型,以及传入的最小值的类型来生成一个新树。这让类型系统告诉我是否混淆了它们
repmin::树a->树a
repmin=(loop.uncurry)copyRose
copyRose::Ord a=>树a->b->(树b,a)
copyRose(节点x ts)最终最小值
|(ts',m)我不知道,但我真的不喜欢你的unzipidmimum
函数,因为它不计算min
。我认为可能有更好的方法。@dfeuer会添加类似于let bmin'=min b bmin in in(join seq)bmin'
的内容使事情变得更好吗?不,你需要重塑事物。@dfeuer“重塑”是什么意思?我们是否需要整体地重塑unzipidmimum
或copyTree
?@dfeuer也许unzipidmimum=foldr(\(a,b)(as,!bmin)->(a:as,b`min`bmin))([],maxBound::Int);(fo',!y)=最小值
将按原样计算最小值(从右到左,自下而上)。它仍然会以元组的形式一次展开整个树结构的副本,最有可能的是,首先,然后在请求结果树时从顶部重新遍历它,自顶向下重建节点。(续)谢谢你的回答。我试图将我的解决方案与中的解决方案相匹配(pdf-9.1“therepmin
问题”第122页,第130页)。它有同样的问题吗?@ZhiltsoffIgor,是的,有。我刚刚意识到用我的方法计算最小值是没有必要的;实际上,你可以做一些事情,比如你的方法,让每件事都变得严格。但我的方式更优雅地处理空列表挑战。此外,“thunks之树”是什么意思?从我的角度来看,每个节点中的递归调用从其所有子节点收集thunk并继续进行。我在上面写的(join-seq)(min-b-bmin)
会严格执行它吗?我想我们不需要let
,因为join f
的参数正在被共享。@zhiltsofigorseq x y
的意思是,“当y
被强制时,也强制x
”。因此,seq x
什么也没说。这就是我对它的理解。
loop f b = let cd = f (b, snd cd) in fst cd