repmin如何在Haskell的树中放置值?

问题描述

我真的很喜欢db=psycopg2.connect(host="localhost",user="anton",password="password",dbname="mytest",options='-c standard_conforming_strings=off') 问题:

写下repmin,它一次将树中的所有数字替换为最小值。

如果我在python中编写类似的代码,我将通过它们的引用传递值(假设用一个元素列表代替数字就足够了):

repmin :: Tree Int -> Tree Int

在我看来,这是一种在Haskell中打结解决方案的合适方法(我为rose trees from Data.Tree编写了这种方法):

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)

但是,我认为解决方案的工作方式大不相同。这是我对后一种的理解:

让我们稍微重写loop for (->)

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 for (->)的工作方式,因为loop f b = let cd = f (b,snd cd) in fst cd 的懒惰程度与snd中的模式匹配一​​样。

因此,当let穿过树时,它是:

  • 在树中建立最小值以作为对的第二个元素返回。
  • 在每个节点中留下repmin

因此,遍历结束时,程序会知道snd $ copyRose (tree,m)的值(即树中的最小值),并能够在某些节点上显示正在计算树的数量

我对Haskell的snd $ copyRose (tree,m)理解正确吗?

解决方法

这不是一个扩展的评论,而是一个答案,但是我并不认为您的实现是单次通过。它看起来像遍历树一次,看起来像是遍历了树,产生了一个新的,由懒惰生成的树和全局最小值,但实际上,它 产生了一个由懒惰生成的树和一棵巨大的树。最终将计算出最小值的重击为了避免这种情况,您可以通过急切生成树并随时随地跟踪最小值来接近Python代码。

您会注意到,我已将类型从Int推广到任意Ord类型。您还将注意到,我习惯于使用不同的类型变量来指代给定树中的元素类型以及为生成新树而传入的最小值的类型,这使类型系统可以告诉我是否将它们混合使用上。

repmin :: Tree a -> Tree a
repmin = (loop . uncurry) copyRose

copyRose :: Ord a => Tree a -> b -> (Tree b,a)
copyRose (Node x ts) final_min
  | (ts',m) <- copyForest x ts final_min
  = (Node final_min ts',m)

copyForest :: Ord a => a -> [Tree a] -> b -> ([Tree b],a)
copyForest !m [] _final_min = ([],m)
copyForest !m (t : ts) final_min
  | (t',m') <- copyTree m t final_min,(ts',m'') <- copyForest m' ts final_min
  = (t' : ts',m'')

copyTree :: Ord a => a -> Tree a -> b -> (Tree b,a)
copyTree !m (Node x ts) final_min
  | (ts',m') <- copyForest (min m x) ts final_min
 = (Node final_min ts',m')

锻炼:使用ReaderT来传递全局最小值,使用State来跟踪最小值,以单子形式重写。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...