我想要一个递归定义的函数f::[type]->[type]
,大致如下:
它以包含1个元素x
的列表开头。然后它应用3“生成器函数”让我们调用它们
generatorA
,generatorB
和generator C
,所有函数::type->type
,并将这些函数添加到列表中 IF ,它们接受某些条件。对于每个接受的生成数字,它会重复应用生成器A
,B
和C
以及测试条件,直到条件测试为假。因此,对于列表中接受的每个元素,将生成3个新元素并进行列表测试。
一个例子是:
f::[int]->[Int]
generatorA x = x+1
generatorB x = 2x+1
generatorC x = 3x+1
条件:必须是复合数(不是素数)。
计算f [10]
它应该从generatorA 10 = 11
开始,弃掉它。
generatorB 10 = 21
接受然后:
generatorA 21 = 22
接受然后:generatorA 22 = 23
素丢弃。generatorB 21 = 43
弃牌generatorC 21 = 64
接受等等。问题是:我如何编写函数f
?我不知道怎么开始。我最好的猜测是
f (x:xs)
|condition==True = (something something)
|otherwise = xs
where
a=generatorA x
b=generatorB x
c=generatorC x
感谢您的帮助。
答案 0 :(得分:3)
如果以单例列表开头,它也可以以单个值作为参数开始。
ga x = [y | let y=x+1, composite y] >>= (\x-> x:f x)
gb x = [y | let y=2*x+1, composite y] >>= (\x-> x:f x)
gc x = [y | let y=3*x+1, composite y] >>= (\x-> x:f x)
f :: Integer -> [Integer]
f x = ga x ++ gb x ++ gc x
我使用Integer
来避免溢出问题。测试:
*Main> take 40 $ f 10
[21,22,45,46,93,94,95,96,289,290,291,292,585,586,1173,1174,1175,1176,1177,1178,1
179,1180,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,4741,4742,4743,4744,4
745,4746,4747,4748]
也可以实现 f
以更浅的方式产生结果,
import Data.List
f x = concat $ transpose [ga x, gb x, gc x]
测试:
*Main> take 80 $ h 10
[21,22,64,45,65,46,129,91,66,136,130,93,196,92,259,273,133,94,388,183,393,274,26
1,187,134,274,260,820,589,280,777,93,267,275,391,95,394,184,519,1641,400,188,116
5,275,590,549,262,561,135,185,778,2461,1180,189,778,550,268,276,392,375,1179,549
,261,1642,801,841,1166,94,395,550,784,96,403,185,520,2462,1768,562,1555,276]
答案 1 :(得分:2)
使用Data.Tree.unfoldTree :: (b -> (a, [b])) -> b -> Tree a
构建您的值列表。如果您想预订,请使用flatten
,或concat . Data.Tree.levels
获得广度优先订单。
f x = flatten $ unfoldTree (\b -> (b, filter composite (map ($ b) [ga, gb, gc]))) x
如果您不想要该元素,此列表将包含初始种子元素。只需致电tail
。