2013-04-27 54 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即可。