所以我输入2个排序列表,可以是无限的。 我必须编写一个函数prod,它基本上以排序顺序返回笛卡尔积坐标的乘积。
示例:
prod [2,4,5,10] [2,3] -> [4,6,8,10,12,15,20,30]
对于有限列表,它就像
一样简单import Data.List
prod xs ys = sort [x*y | x<-xs, y<-ys]
但问题是当我尝试将它与无限列表一起使用时。我在想,因为输入是排序的,我可以使用Data.List.Ordered.unionAllBy
,但我无法理解如何使用它。比较选项让我困惑。
所以我可以使用我写的函数:
sequence2 xs ys = [[i*j| i<-xs]|j<-ys]
示例:
sequence2 [2,4,5] [3,4,5] -> [[6,12,15],[8,16,20],[10,20,25]]
我想我的解决方案看起来像是:
Data.List.Ordered.unionAllBy (comparison) (sequence' xs ys)
任何提示我如何修改它以使用无限列表?
答案 0 :(得分:4)
传递给unionAllBy
的比较是一个具有相同类型的函数,并遵循与Ord
实例中的compare
函数相同的规则。如果您有Ord
个实例,则可以使用unionAll
代替unionAllBy
。
unionAllBy :: (a -> a -> Ordering) -> [[a]] -> [a]
unionAll :: Ord a => [[a]] -> [a]
compare :: Ord a => a -> a -> Ordering
unionAll = unionAllBy compare
比较函数需要两个对象并说明它们的顺序:LT
,EQ
或GT
。关于compare
应该做什么的最佳解释可能是Ord
class in the standard prelude
compare x y | x == y = EQ | x <= y = LT | otherwise = GT x <= y = compare x y /= GT x < y = compare x y == LT x >= y = compare x y /= LT x > y = compare x y == GT
unionAll
函数将组合sequence2
列表,以便从列表之间删除重复项。 unionAll
不会删除单个输入列表中的重复项。
> unionAll $ sequence2 [2,4,5] [3,4,5]
[6,8,10,12,15,16,20,25]
^
only one twenty
它还会按顺序展平sequence2
应用于无限列表
> take 12 . unionAll $ sequence2 [2,4..] [3,5..]
[6,10,12,14,18,20,22,24,26,28,30,34]
如果您想保留重复项,请改用mergeAll
。
> mergeAll $ sequence2 [2,4,5] [3,4,5]
[6,8,10,12,15,16,20,20,25]
^ ^
two twenties