Data.List.Ordered.unionAllBy比较无限列表

时间:2015-09-16 14:36:36

标签: haskell

所以我输入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)

任何提示我如何修改它以使用无限列表?

1 个答案:

答案 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

比较函数需要两个对象并说明它们的顺序:LTEQGT。关于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