由於列表理解通常給笛卡爾乘積,你也可以嘗試從ZipListControl.Applicative
GHCi> :m + Control.Applicative
GHCi> :info ZipList
newtype ZipList a = ZipList {getZipList :: [a]}
-- Defined in `Control.Applicative'
instance Functor ZipList -- Defined in `Control.Applicative'
instance Applicative ZipList -- Defined in `Control.Applicative'
GHCi> let combine f xs ys = getZipList $ f <$> ZipList xs <*> ZipList ys
GHCi> :t combine
combine :: (a2 -> a1 -> a) -> [a2] -> [a1] -> [a]
GHCi> combine (-) [10,9..] [1..10]
[9,7,5,3,1,-1,-3,-5,-7,-9]
GHCi>
不要怕ZipList
,它只是包裝的列表,你可以將列表轉換成ZipList
和使用getZipList
其轉換回。 This chapter在LYAH給你一些關於如何使用它的解釋,玩得開心!
BTW,您可以使用在上面的例子中裸列表,它給你的笛卡爾乘積:
GHCi> let combine1 f xs ys = f <$> xs <*> ys
GHCi> :t combine1
combine1 :: Applicative f => (a1 -> a -> b) -> f a1 -> f a -> f b
GHCi> combine (-) [10,9..1] [1..10]
[9,8,7,6,5,4,3,2,1,0,8,7,6,5,4,3,2,1,0,-1,...]
GHCi>
正如你所看到的,有合併兩個列表連接起來的方式有兩種,一種是認爲如果您從xs=[1,2]
獲取一個可能的值,並且從ys=[3,4]
獲取另一個可能的值來創建元組,則您將最終得到所有可能性:[(1,3),(1,4),(2,3),(2,4)]
,這基本上是[(x,y)| x <- xs, y <-ys]
所說的內容。但是還有另外一種合併兩個列表的方法:每次你從兩個列表中同時獲取一個元素,並且創建一個元素,直到列表中的一個到達其末尾,這就是ZipList
合併在一起的方式。
該函數更熟知爲'zipWith'。你可以用一個列表理解來實現它,如下所示:'f xs ys = [f x y | (x,y)< - zip xs ys]' – fjh
謝謝,現在該功能起作用! :-) – bolle