正如标题所说,我需要这个:
getAllTrees :: [Int] -> [Tree Int]
getAllTrees xs = undefined
树在哪里
data Tree x
= Null
| Leaf x
| Node (Tree x) x (Tree x)
我会感激任何帮助,即使是最小的线索:) 感谢
答案 0 :(得分:11)
我通常发现使用list monad最容易解决这些问题。我们可以通过以下推理来定义getAllTrees
:
唯一的零项目树是Null
:
getAllTrees [] = return Null
一个元素中只有一个树,即Leaf
:
getAllTrees [x] = return $ Leaf x
当我们有多个元素时,我们可以用所有可能的方式拆分列表以确定我们应该如何分支,然后从每个列表递归生成子树。假设我们有一个函数splits :: [a] -> [([a], [a])]
,它返回分割列表的所有方法,例如:
> splits [1..3]
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])]
然后我们可以使用list monad定义getAllTrees
的最终大小写。这允许我们编写类似于我们只关注一个案例的代码,monad将为我们提供所有组合。
getAllTrees xs = do
(left, x : right) <- splits xs
Node <$> getAllTrees left <*> pure x <*> getAllTrees right
第一行拆分输入列表,并将第二部分中的第一项作为中间元素。第二部分为空时的情况与模式不匹配,因此它会被丢弃,因为这是列表monad处理模式匹配失败的方式。
第二行使用应用语法来说我们希望结果是一个节点列表,由left
列表中的子树的所有组合,固定的中间元素x
组成,以及right
列表中的所有子树。
剩下的就是实施splits
。看一下上面的例子,我们很容易看到我们可以将列表的inits
和tails
与zip
放在一起:
splits xs = zip (inits xs) (tails xs)
在口译员中进行快速健全检查的时间:
> mapM_ print $ getAllTrees [1..3]
Node Null 1 (Node Null 2 (Leaf 3))
Node Null 1 (Node (Leaf 2) 3 Null)
Node (Leaf 1) 2 (Leaf 3)
Node (Node Null 1 (Leaf 2)) 3 Null
Node (Node (Leaf 1) 2 Null) 3 Null
> length $ getAllTrees [1..5]
42
看起来我们已经完成了!一些重要的经验教训: