Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
显示树Haskell_Haskell - Fatal编程技术网

显示树Haskell

显示树Haskell,haskell,Haskell,考虑以下数据类型 data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a 我正在尝试定义一个Show实例(不导入任何模块或使用派生),它将像这样显示树 Main*> let a = Branch "x" (Branch "y" (Leaf 4) (Leaf 7)) (Leaf 9) Main*> a "x" "y" 4 7 9 到目前为止,这就是我想到的 findD

考虑以下数据类型

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a
我正在尝试定义一个Show实例(不导入任何模块或使用派生),它将像这样显示树

Main*> let a = Branch "x" (Branch "y" (Leaf 4) (Leaf 7)) (Leaf 9)
Main*> a
"x"
     "y"
          4
          7
     9
到目前为止,这就是我想到的

findDepth (Leaf a) = 0
findDepth (Branch a (b) (c)) = 1 + (max (findDepth b) (findDepth c))
data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a
instance (Show a, Show b) => Show (Tree a b) where
     show (Leaf x) = show x
     show (Branch a (b) (c)) =
          show a ++ "\n" ++ s2 ++ show b ++ "\n" ++ s2 ++ show c ++ "\n" ++ s1
               where
                    d = findDepth (Branch a (b) (c))
                    s1 = addSpace (d-1)
                    s2 = addSpace d
                    addSpace n = replicate n '\t'

不幸的是,这会使深度最低的节点缩进最多,而深度最高的节点缩进最少。我知道findDepth函数实际上应该给leaf最大的值,给branch最小的值,但是无法找到一种方法来递归地为这两个参数编写函数。有什么建议吗?

实际上,不需要额外的
findDepth
功能-您可以轻松地遍历树并在每次向孩子们显示时增加深度:

import Text.Printf

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a

instance (Show a, Show b) => Show (Tree a b) where
  show = showAtLevel 0
    where
      showAtLevel l (Leaf x) = addSpace l ++ show x
      showAtLevel l (Branch x (lt) (rt)) = printf "%s%s\n%s\n%s" (addSpace l) (show x) (showAtLevel (l + 1) lt) (showAtLevel (l + 1) rt)
      addSpace = flip replicate '\t'
测试用例:

*Main>  let a = Branch "x" (Branch "y" (Leaf 4) (Leaf 7)) (Leaf 9)
*Main> a
"x"
    "y"
        4
        7
    9
*Main> Branch "x" (Branch "y" (Leaf 4) (Branch "z" (Leaf 42) (Leaf 314))) (Leaf 9)
"x"
    "y"
        4
        "z"
            42
            314
    9

这里有一个没有完整解决方案的提示:编写一个函数
showWithDepth::Int->Tree->String
,传递到目前为止的“累计深度”。然后您可以使用深度0编写
show=show


请注意,一般情况下,您不应该像这样编写
show
实例,因为show实例的“半标准”工作原理应该与派生实例类似,并生成类似于有效Haskell代码的内容。(另外,当出现
Read
实例时,我们希望
Read.show==id

真是太感谢了much@Alec,你总是受欢迎的!你有什么理由不回答这四个问题吗尝试了一种没有复制的递归方法,比如
show tree=unlines(映射缩进(go tree)),其中go(Leaf v)=[show a];go(Branch v l r)=show v:indent(go l++go r);indent=map('\t':)
?只是复制了一些操作代码,以尽量减少更改。使用
未联机的有趣方法似乎很干净。你不想将其作为答案发布吗?如果你不认为这是另一个问题的重复,请随意添加评论(别忘了添加
@Zeta
).尽管如此,你仍然可以接受其中一个发布的答案。顺便问一下,目前是否有哈斯克尔讲座?一些最新的问题非常相似。