我想要计算树中有多少元素“尊重”某个规则。
例如:
对于数据类型:
data Tree = Leaf Int | Node Tree Int Tree
和函数签名:
nSatisfy :: (Int->Bool) -> Tree -> Int
输入:
(>0) Tree
它应该返回树的值(> 0)。
这是我尝试过的:
nSatisfy :: (Int->Bool) -> Tree -> Int
nSatisfy condition Leaf x = if condition x then 1 else 0
nSatisfy condition (Node left x right)
|(if condition x then 1 else 0) + nSatisfy condition Tree
| otherwise = nSatisfy condition left || nSatisfy condition right
任何帮助?
更新:
我找到了一种更简单的方法:
nSatisfy :: (Int->Bool) -> Tree -> Int
nSatisfy n (Leaf x) = if n x then 1 else 0
nSatisfy n (Node left x right) = (if n x then 1 else 0) + (nSatisfy n left) + (nSatisfy n right)
答案 0 :(得分:3)
该函数一次执行太多:计数,检查谓词并遍历复杂类型。
我建议写一个函数
listFromTree :: Tree -> [Int]
并使用nSatisfy
以及前奏函数listFromTree
和length
构建您的filter
。
编辑:OP自己找到了一个有效的答案,现在这里是我的代码:
nSatisfy' p = length . filter p . listFromTree listFromTree :: Tree -> [Int] listFromTree (Leaf x) = [x] listFromTree (Node left x right) = listFromTree left ++ [x] ++ listFromTree right
检查某些内容的功能,即a -> Bool
通常称为predicate,并在filter中使用p
进行缩写。 n
通常是整数,而不是函数。
答案 1 :(得分:2)
您的更新版本没有错误。然而,路易斯·卡西利亚斯和弗兰基鼓励你考虑将代码中的想法分解成尽可能小的部分。这通常是处理编程问题的最佳方法,原因如下:
人脑只能立刻想到这么多。如果你将问题分解成不同的部分或层次,并且一次只考虑一个问题,那么你就有更好的机会正确地解决问题。
您将创建可以重复使用以解决其他问题的函数,以及可以重复使用以解决其他问题的思维方式
您将能够分别测试每个解决方案。在这种情况下,问题很简单,足以测试整个解决方案,但在大多数现实情况下,等到你开始测试之前有一个完整的解决方案将导致你陷入“我知道这是错的,但我不是”的兔子洞知道在哪里“。
一旦你将问题分解成小块,你就更有可能发现其他人已经解决了这些问题。很快,您的Haskell研究将引导您进入多态数据结构和功能。通过稍微概括一下Tree
类型,您将能够使用toList
,fmap
和sum
等库函数,从其他人的解决方案中构建解决方案为你写的。
答案 2 :(得分:1)
嗯,这是一个暗示。如果将其分为三个部分,则可以更轻松地解决此问题:
mapTree :: (Int -> Int) -> Tree -> Tree
函数,它将提供的函数应用于树中的每个Int
。Int
的功能,如果满足您的条件,则返回1
,否则为0
。sumTree :: Tree -> Int
函数,它对树中的所有Int
求和。然后,您可以将这三个部分放在一起,以便轻松解决您的问题。而且,mapTree
和sumTree
对其他问题有用。