Haskell二叉树递归

时间:2015-10-02 19:02:50

标签: haskell recursion

我是haskell的初学者,我需要根据List(Path)中指定的方向在树中显示值。我已经在数据结构下面听了,我想理解为什么我实现的递归功能是错误的

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

//当我执行此操作时,它会在valueAt处显示非详尽的功能。所以我猜测我的递归思想是错误的。任何人都可以解释原因。

2 个答案:

答案 0 :(得分:1)

你没有处理案件valueAt [] someTree。行valueAt (p:ps) ...仅匹配以p开头并继续ps非空列表。 ps可能为空,但p:ps永远不会。

如果使用标志-Wall进行编译,GHC应该在编译时对此进行警告。我强烈推荐这个。

作为一种风格建议,请避免使用p == ...等守卫,因为它们不会执行任何模式匹配。尝试改为

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

答案 1 :(得分:0)

valueAt的模式匹配不包括[],因为(p:ps)在空列表中失败。但是,它没有必要这样做。警卫按照他们的编写顺序进行评估,这意味着您的p == Lp == R警卫会在<{em>} ps == []案例之前进行评估。换句话说,在递归情况之后放置了边缘情况,导致模式匹配无效。这段代码应该解决这个问题。

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

但是,您的代码还有另一个问题。该函数具有类型描述valueAt :: Path -> Tree a -> Maybe a,但在您的边缘情况(ps == [])中,Just具有类型a -> Maybe a; Just适用于太少的参数。试试这个。

                           | ps == [] = Just a

既然您的错误已经修复,我还建议您从警卫和==转移到模式匹配。它会更简单,更快速,更不容易出错。

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