由于列表理解通常给笛卡尔乘积,你也可以尝试从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