你的第一个定义,kart xs ys = [(x,y) | x <- xs, y <- ys]
,相当于
kart xs ys = xs >>= (\x ->
ys >>= (\y -> [(x,y)]))
where
(x:xs) >>= g = g x ++ (xs >>= g)
(x:xs) ++ ys = x : (xs ++ ys)
是顺序操作。将它们重新定义为交替操作,
(x:xs) >>/ g = g x +/ (xs >>/ g)
(x:xs) +/ ys = x : (ys +/ xs)
[] +/ ys = ys
你的定义也应该适合无限列表:
kart_i xs ys = xs >>/ (\x ->
ys >>/ (\y -> [(x,y)]))
testing,
Prelude> take 20 $ kart_i [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(1,103),(2,102),(1,104),(4,101),(1,105),(2,103)
,(1,106),(3,102),(1,107),(2,104),(1,108),(5,101),(1,109),(2,105),(1,110),(3,103)]
礼貌地《理性的阴谋家》。 (也可以看看康达、康迪、康德、康杜).
另一种更明确的方法是创建单独的子流并将它们组合起来:
kart_i2 xs ys = foldr g [] [map (x,) ys | x <- xs]
where
g a b = head a : head b : g (tail a) (tail b)
这实际上产生了完全相同的结果。但现在我们可以更好地控制如何组合子流。我们可以更加对角:
kart_i3 xs ys = g [] [map (x,) ys | x <- xs]
where -- works both for finite
g [] [] = [] -- and infinite lists
g a b = concatMap (take 1) a
++ g (filter (not . null) (take 1 b ++ map (drop 1) a))
(drop 1 b)
所以现在我们得到
Prelude> take 20 $ kart_i3 [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(2,102),(1,103),(4,101),(3,102),(2,103),(1,104)
,(5,101),(4,102),(3,103),(2,104),(1,105),(6,101),(5,102),(4,103),(3,104),(2,105)]
和一些在 SO 上搜索我还找到了一个诺曼·拉姆齐的回答似乎还有另一种生成序列的方式,将这些子流分成四个区域 - 左上角、顶行、左列,以及递归其余部分。他的merge
有和我们一样的+/
here.
你的第二个定义,
genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
相当于只是
genFromPair (e1, e2) = [0*e1 + y*e2 | y <- [0..]]
因为名单[0..]
是无限的,没有机会得到任何其他值x
发挥作用。This这是上述定义都试图避免的问题。