Haskell的叶子树 - 非详尽的模式

时间:2015-01-19 01:31:23

标签: haskell

此函数遵循Bools的路径,分别根据False或True向左或向右移动

data LTree a = Leaf a 
             | Fork (LTree a) (LTree a)
             deriving (Show)

select :: LTree a -> [Bool] -> (Maybe a)
select (Fork (Leaf a) (Leaf b)) (l:ls)  = if l==False  then Just a 
                                                       else Just b
select (Fork l r) (b:bs) = if b==False  then select l bs
                                        else select r bs

问题是,LTree没有声明Empty值,我怎么知道它是我的函数中的节点或分支?

2 个答案:

答案 0 :(得分:6)

询问编译器

GHC可以在编译时警告您非详尽的模式,而不是等待运行时间来发现它们。如果我将您的代码放入文件并使用-fwarn-incomplete-patterns flag

进行编译
ghc -fwarn-incomplete-patterns nonExhaustiveLeafTree.hs

它会产生以下错误消息:

    Pattern match(es) are non-exhaustive
    In an equation for `select':
        Patterns not matched:
            (Leaf _) _
            (Fork (Fork _ _) _) []
            (Fork (Leaf _) (Fork _ _)) []
            (Fork (Leaf _) (Leaf _)) []

在添加rule you suggested in your answer以涵盖[]之后,它仍会生成关于树为Leaf _

的任何内容的警告
    Pattern match(es) are non-exhaustive
    In an equation for `select': Patterns not matched: (Leaf _) _

涵盖所有内容

如果我们彼此分开处理LeafFork s,我们可以轻松覆盖所有模式。这也消除了重复的代码,当它的直接后代离开时,决定在Fork上使用哪种方式。

你知道当你到达Leaf时会有结果,而且没有路可走了。

select (Leaf a) [] = Just a

当您到达Leaf并且还有一条路径需要遵循时,您需要决定该做什么。

select (Leaf a) (l:ls) = ????

就像你在答案中提到的那样,当你没有路径并且你处于Fork时,你就会知道没有结果。

select (Fork _ _) [] = Nothing

您可以简化当存在分支和单个规则的路径时发生的情况。

select (Fork l r) (b:bs) = if b
                           then select r bs
                           else select l bs

答案 1 :(得分:0)

好的,

这很简单,我猜需要休息一下:

缺少这个:

select (Fork l r) [] = Nothing