自定义构造函数Haskell上的模式匹配
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义构造函数Haskell上的模式匹配相关的知识,希望对你有一定的参考价值。
我的自定义类型是:
data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq)
我需要写一个函数
foo :: Eq a => a -> Tree a -> [Tree a]
例
foo 3 (Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3])
-- this should print [Node [leaf 5, leaf 3, leaf 6], leaf 6, leaf 44] i.e - all elements that follow a "Leaf 3" in the Tree
我的代码如下(使用模式匹配)
foo n (Leaf _) = []
foo n (Node (Node z):y:xs) = if length (Node z):y:xs < 2 then []
else (foo n (Node z)):(foo n y:xs)
foo n (Node (Leaf z):y:xs) = if length (Leaf z):y:xs < 2 then []
else if Leaf n == Leaf z then [y]:(foo n y:xs)
else (foo n y:xs)
但是我收到一个错误:
• Couldn't match expected type ‘Tree a’ with actual type ‘[Tree a]’
• In the pattern: Node (Node z) : y : xs
但Node (Node z) : y : xs
模式可以代表输入
Node [Node [Leaf 4, Leaf 2], Leaf 6, Leaf 9, Leaf 1]
我说错了吗?这对我来说似乎很完美。
那么,为什么模式匹配失败?
答案
我在repl.it上设置了一个示例,但代码如下。
我做的第一件事是为函数添加一个更具体的签名,以便更容易推理。一旦完成所有工作,请随意将其更改回原点签名。从具体到抽象,比从另一个方向转移更容易。
- 第一个问题是模式中缺少括号(这意味着你没有使用
Tree a
,而是试图与[Tree a]
匹配。原来的(Node (Node z):y:xs)
评估如下:((Node (Node z)):y:xs)
。为了方便起见,我在下面的图案中添加了all@
,但是你可以取代它,它不是必不可少的。 - 第二个问题是你真的试图将
[Tree a]
塞进Tree a
,因为这就是y:xs
在foo n y:xs
的意思,所以我用Node (y:xs)
取代它,这是一个Tree a
。 - 第三个问题是
foo
的模式匹配并非详尽无遗,最后添加了一个包罗万象,你会想要考虑你的预期行为并清理它。
代码如下:
module Main where
data Tree a = Leaf a | Node [Tree a] deriving (Show, Eq)
foo :: Int -> Tree Int -> [Tree Int]
foo n (Leaf _) = []
foo n (Node all@((Node z):xs)) = if length all < 2 then []
else (foo n (Node z)) ++ (foo n (Node xs) )
foo n (Node all@((Leaf z):y:xs)) = if length all < 2 then []
else if Leaf n == Leaf z then [y] ++ (foo n (Node (y:xs)))
else (foo n (Node (y:xs)))
foo _ _ = []
myTree :: Tree Int
myTree = Node [Leaf 1, Leaf 3, Node [Leaf 5, Leaf 3, Leaf 6], Leaf 4, Leaf 3, Leaf 44, Leaf 3]
main :: IO ()
main = do
print (foo 3 myTree)
输出:
[Node [Leaf 5,Leaf 3,Leaf 6],Leaf 6,Leaf 44]
以上是关于自定义构造函数Haskell上的模式匹配的主要内容,如果未能解决你的问题,请参考以下文章