Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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_Recursion - Fatal编程技术网

Haskell二叉树递归

Haskell二叉树递归,haskell,recursion,Haskell,Recursion,我是haskell的初学者,需要根据列表(路径)中指定的方向在树中显示值。我在下面列出了数据结构,我想了解为什么我实现的递归特性是错误的 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

我是haskell的初学者,需要根据列表(路径)中指定的方向在树中显示值。我在下面列出了数据结构,我想了解为什么我实现的递归特性是错误的

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表示非穷举函数。所以我猜我的递归思想是实现错误的。有人能解释一下原因吗。

您没有在[]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

valueAt
的模式匹配不包括
[]
,因为
(p:ps)
将在空列表中失败。但是,它没有必要这样做。按照编写顺序对保护进行评估,这意味着在您的
ps=[]
案例之前对
p==L
p==R
保护进行评估。换句话说,您已经将您的边缘案例放在递归案例之后,导致了无效的模式匹配。这段代码应该可以解决这个问题

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=[]
),
只是
具有类型
a->Maybe a
<代码>仅
应用于太少的参数。试试这个

                           | 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

正确缩进代码<代码>值按原样,继续上一行
。。。8) )
!不要在这里使用
==
。它有它的用途,但它根本不属于这段代码。在这里使用模式匹配而不是警卫。嘿,非常感谢,这帮了大忙,是的,警卫让它看起来更复杂。谢谢你花时间在这上面。