合并未绑定数量的有序无限序列

时间:2011-05-14 06:07:44

标签: haskell

我想生成所有自然数以及它们在素数因子中的分解,直到某个阈值。

我提出了以下功能:

vGenerate :: [a]                 -- generator set for monoid B* (Kleene star of B)
          -> (a, (a -> a -> a)) -- (identity element, generating function)
          -> (a -> Bool)        -- filter
          -> [a]                -- B* filtered
vGenerate [] (g0,_) _ = [g0]
vGenerate (e:es) (g0,g) c = 
    let coEs = vGenerate es (g0,g) c
        coE  = takeWhile (c) $ iterate (g e) g0
    in concatMap (\m -> takeWhile (c) $ map (g m) coE) coEs
然后,gen生成所有自然数及其主要因子:

gen threshold =
     let b = map (\x -> (x,[x])) $ takeWhile (<= threshold) primes
         condition = (<= threshold) . fst
         g0 = (1,[])
         g = \(n,nl)(m,ml) -> ((n*m), nl ++ ml)
     in vGenerate b (g0,g) condition

primes = [2,3,5,7,11,.. ] -- pseudo code

我有以下问题:

  • 事先并不知道我们需要多少个数字。我们可以修改vGenerate,使其以一个懒惰的无限素数列表开始,并按递增顺序生成所有因子分解?挑战在于我们有一个无限的素数列表,对于每个素数,该素数的无限列表,然后必须采取所有可能的组合。列表通过增加第一个元素自然排序,因此它们可以懒得生成。

  • 我用monoid描述了vGenerate,并打算尽可能地保持抽象,但这可能只是混淆了代码?我想稍后概括它(更多的是作为练习而不是实际使用),例如用于在某些约束内生成栅格点,也可以放在monoid上下文中,所以我认为这是一个很好的开始摆脱对问题空间的所有引用(在casu:primes中)。但我觉得过滤函数不适合抽象:生成必须按照c测试的度量单调的顺序发生,因为一旦c不满足就终止递归。有什么建议吗?

1 个答案:

答案 0 :(得分:6)

data-ordlist包中查看mergeAll :: Ord a => [[a]] -> [a]。只要序列被排序,它就会合并一个未绑定数量的无限序列,并且序列的头部是有序的。之前我曾将它用于类似的问题,例如生成2^i*3^j形式的所有数字。

> let numbers = mergeAll [[2^i*3^j | j <- [0..]] | i <- [0..]]
> take 20 numbers
[1,2,3,4,6,8,9,12,16,18,24,27,32,36,48,54,64,72,81,96]

您应该能够扩展它以生成包含其分解的所有数字。