无限计数器的无限列表

时间:2012-01-06 19:30:39

标签: haskell infinite

对于那些有可疑头脑的人来说,这不是家庭作业,只是好奇。

给定一个有限的字母表,是否有可能构建一个由反向词汇顺序的字母表组成的无限长单词列表?

即。给出字母"ab"

是否可以构建列表:

["aaaaaa...", "baaaaa...", "abaaaa...", "bbaaaa...", "aabaaa...", ...]

其中...表示扩展到无限长度的列表(和列表列表)。

天真的尝试是:

counters alphabet = [c:ounter | ounter <- counters alphabet, c <- alphabet]

但这不起作用,因为它是递归的。

当然,对于工作版本,如果您尝试打印结果,您只会看到第一个元素被打印为字母表中第一个元素的无限列表。但是,您应该能够这样做:

mapM_ (print . take 2) . take 4 . counters $ "ab"

并查看输出:

aa
ba
ab
bb

6 个答案:

答案 0 :(得分:11)

为什么不fix呢?

ghci> let bar = let foo ~(st:sts) = [c:st | c <- "ab"] ++ foo sts in fix foo
ghci> take 5 . map (take 5) $ bar
["aaaaa","baaaa","abaaa","bbaaa","aabaa"]
take 10 . map (take 5) $ bar
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"]

答案 1 :(得分:7)

可能不是最有效的解决方案,但至少它有效:

counters alphabet = map f [0..]
  where f n = let (q, r) = quotRem n (length alphabet) in alphabet !! r : f q
> take 10 $ map (take 5) $ counters "ab"
["aaaaa","baaaa","abaaa","bbaaa","aabaa","babaa","abbaa","bbbaa","aaaba","baaba"]

答案 2 :(得分:6)

您可能会发现以下方法有趣/令人困惑:

duplicates s ss = cycle ss : duplicates s (ss >>= \c -> s >> [c])
counters = transpose . join duplicates

这是因为观察到第一个字母遵循模式"ababab...",第二个字母遵循模式"aabbaabbaabb...",第三个字母遵循模式"aaaabbbbaaaabbbb..."等。

答案 3 :(得分:2)

这个怎么样?

f@(a:as) = a:('b':a):concatMap (\x -> ['a':x,'b':x]) as where a = ['a','a'..]

(\x -> ['a':x,'b':x])如果您认为Applicative更优雅,也可以([('a':),('b':)] <*>) . pure写成{{1}}。

答案 4 :(得分:1)

这个过程看起来像编码左边的最低位数的基数为N的数字,所以我们可以将其作为

  1. 使用字母作为字母,制作一个“以N为基础”功能f
  2. map f[0..]
  3. repeat $ head alphabets附加到列表的每个元素。

答案 5 :(得分:1)

另一个版本基于丹尼尔的想法:

counters = transpose $ map cycle $ iterate (>>= \x -> [x,x]) "ab"