2013-04-27 55 views
2

我想要一个功能f::[type]->[type]是递归的一个粗略的定义是这样的:写作与条件的递归函数在Haskell:

它开始用1元x列表。然后它应用3个“发电机功能”让我们叫他们 generatorA,generatorBgenerator C,所有功能::type->type,并将那些添加到列表如果他们接受一些条件。对于每个接受的生成数,则重复施加发生器ABC和试验条件,直至条件测试为假。因此,对于列表中接受的每个元素,将生成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 

感谢您的帮助。

回答

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 s来避免溢出问题。测试:

*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] 
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即可。