简体   繁体   English

Haskell 二叉树递归

[英]Haskell Binary Tree Recursion

I am a beginner in haskell and I need to display the value in a tree based on directions specified in a List (Path).我是haskell的初学者,我需要根据列表(路径)中指定的方向在树中显示值。 I have liste below the Data structures , I want to understand why my recursive feature that i have implemented is wrong我在数据结构下面列出了,我想了解为什么我实现的递归功能是错误的

import Data.List

 data Step = L | R
 deriving(Eq,Show)

type Path = [Step]  

 data Tree a = Node a (Tree a) (Tree a)
             | End
        deriving (Eq,Show)

      leaf :: a -> Tree a
      leaf x = Node x End End

     ex :: Tree Int


     ex = Node 4 (Node 3 (leaf 2) End)
               (Node 7 (Node 5 End (leaf 6))
                     (leaf 8))



        valueAt :: Path -> Tree a -> Maybe a
        valueAt (p:ps) (Node a l r)  
                               | p == L = valueAt ps l 
                               | p == R = valueAt ps r
                               | ps == [] = Just           
                               | otherwise = Nothing

// When i execute this it says non exhaustive function at valueAt. // 当我执行它时,它表示 valueAt 处的非穷举函数。 So im guessing my recursive idea was implemented wrong.所以我猜我的递归想法是错误的。 Can anyone explain why .任何人都可以解释为什么。

You did not handle the case valueAt [] someTree .您没有处理valueAt [] someTree的情况。 The line valueAt (p:ps) ... only matches a non empty list starting with p and continuing with ps .valueAt (p:ps) ...仅匹配以p开头并以ps继续的非空列表。 ps might be empty, but p:ps never is. ps可能是空的,但p:ps永远不是。

If you compile with the flag -Wall , GHC should warn about this at compile time.如果您使用标志-Wall编译,GHC 应该在编译时对此发出警告。 I would strongly recommend this.我强烈推荐这个。

As a style suggestion, avoid guards such as p == ... since they do not perform any pattern match.作为样式建议,避免使用p == ...等守卫,因为它们不执行任何模式匹配。 Try instead something like尝试代替类似的东西

valueAt :: Path -> Tree a -> Maybe a
valueAt []     (Node a _ _) = Just a    -- note the "a" !
valueAt (L:ps) (Node _ l _) = valueAt ps l
valueAt (R:ps) (Node _ _ r) = valueAt ps r
valueAt _      End          = Nothing   -- in all the other cases

Your pattern match for valueAt does not cover [] , because (p:ps) will fail on an empty list.您的valueAt模式匹配不包括[] ,因为(p:ps)将在空列表上失败。 However, it is not necessary that it do so.然而,它没有必要这样做。 Guards are evaluated in the order they are written, which means that your p == L and p == R guards are evaluated before your ps == [] case.守卫按照它们的编写顺序进行评估,这意味着您的p == Lp == R守卫您的ps == []案例之前进行评估。 In other words, you have put your edge case after your recursion cases, resulting in an invalid pattern match.换句话说,您将边缘案例放在递归案例之后,导致无效的模式匹配。 This code should fix that.这段代码应该可以解决这个问题。

valueAt (p:ps) (Node a l r)  
                           | ps == [] = Just    
                           | p == L = valueAt ps l 
                           | p == R = valueAt ps r       
                           | otherwise = Nothing

However, your code has another problem.但是,您的代码还有另一个问题。 The function has the type description valueAt :: Path -> Tree a -> Maybe a , but in your edge case ( ps == [] ), Just has type a -> Maybe a ;该函数具有类型描述valueAt :: Path -> Tree a -> Maybe a ,但在您的边缘情况下( ps == [] ), Just具有类型a -> Maybe a ; Just is applied to too few arguments . Just应用于太少的参数 Try this instead.试试这个。

                           | ps == [] = Just a

Now that your errors are fixed, I would also suggest moving from guards and == to pattern matches.现在您的错误已修复,我还建议从守卫和==转移到模式匹配。 It will be simpler, faster, and less error prone.它将更简单、更快且更不容易出错。

valueAt :: Path -> Tree a -> Maybe a
valueAt []     (Node a _ _) = Just a
valueAt (L:ps) (Node _ l _) = valueAt ps l
valueAt (R:ps) (Node _ _ r) = valueAt ps r
valueAt _      _            = Nothing

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM