2015-09-16 28 views
4

所以我有2個排序列表,可以是無限的。 我必須編寫一個函數prod,它基本上返回按照排序順序的笛卡爾積座標的乘積。Data.List.Ordered.unionAllBy比較無限列表

例子:

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) 

任何提示我怎麼能修改此以使用無限列表以及?

回答

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 

比較函數有兩個對象,並說,他們是在什麼樣的順序:LTEQ,或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 
+0

This Works。但有一個問題 - 爲什麼有8個元素而不是9個? 結果應該是 [6,8,10,12,15,16,20,20,25]。從我在文檔中讀到的內容,它應該允許重複,與[2,2,2] [4,4,4]相同的結果[8,8,8]而不是[8,8,8,8, 8,8,8,8,8]。這對我來說似乎很奇怪。 –

+1

來自'unionAll'文檔:「結果將複製元素的次數與任何單個列表中出現的最大次數一樣多。因此,當且僅當每個內部列表都是一個集合時,結果是一個集合「 – Cirdec

+3

@ La'tel unionAll只在每個列表中保留重複*如果要保留* all *重複,則使用mergeAll 。 –