此函数遵循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值,我怎么知道它是我的函数中的节点或分支?
答案 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 _) _
如果我们彼此分开处理Leaf
和Fork
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