Haskell 中的叶树 - 非详尽模式
Leaf Trees in Haskell - non-exhaustive pattern
此函数遵循布尔路径,分别根据 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 值,我怎么知道它是我的函数落入的节点或分支?
好的,
这很简单,我想我需要休息一下:
缺少这个:
select (Fork l r) [] = Nothing
询问编译器
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 _)) []
在添加 以覆盖 []
之后,它仍然会针对任何树是 Leaf _
的地方发出警告
Pattern match(es) are non-exhaustive
In an equation for `select': Patterns not matched: (Leaf _) _
包罗万象
如果我们分别处理 Leaf
和 Fork
,我们可以很容易地涵盖所有模式。这也删除了当 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
此函数遵循布尔路径,分别根据 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 值,我怎么知道它是我的函数落入的节点或分支?
好的,
这很简单,我想我需要休息一下:
缺少这个:
select (Fork l r) [] = Nothing
询问编译器
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 _)) []
在添加 []
之后,它仍然会针对任何树是 Leaf _
Pattern match(es) are non-exhaustive
In an equation for `select': Patterns not matched: (Leaf _) _
包罗万象
如果我们分别处理 Leaf
和 Fork
,我们可以很容易地涵盖所有模式。这也删除了当 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