combine-function与list-comprehension

时间:2014-01-27 15:25:21

标签: haskell list-comprehension

我有一个简单的问题:

combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f (a:as) (b:bs) =  f a b : combine f as bs
combine _  _ _      = [ ]

这是递归的。现在我想使用列表推导来解决同样的问题:

combine f (x:xs) (y:ys) = [ f x y  | x <- (x:xs), y <- (y:ys) ]

但我的问题是元素的组合。我只想合并x1 y1, x2 y2, xs ys ...而不是x1 y1, x1 y2, x1 ys, x2 y1, x2 y2, .....

谢谢!

3 个答案:

答案 0 :(得分:7)

您需要的是parallel list compehension。为了能够使用它,您需要为编译器指定ParallelListComp编译指示:

{-# LANGUAGE ParallelListComp #-}

combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f xs ys = [ f x y | x <- xs | y <- ys ]

编译器将其置于zipWith

的应用程序中
combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine f xs ys = zipWith f xs ys

实际上你的功能是什么,所以:

combine :: (a -> b -> c) -> [a] -> [b] -> [c]
combine = zipWith

答案 1 :(得分:2)

由于列表理解通常会提供笛卡尔积,您也可以从Control.Applicative

尝试ZipList
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将其转换回来。 LYAH中的This chapter给你一些关于如何使用它的解释,玩得开心!

顺便说一下,你可以在上面的例子中使用一个裸列表,它给你笛卡尔积:

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]中获取一个可能的值,则从{{获取另一个可能的值1}}要制作一个元组,你最终会得到所有可能性:ys=[3,4],这基本上就是[(1,3),(1,4),(2,3),(2,4)]所说的。但是还有另一种合并两个列表的方法:每次从两个列表中同时获取一个元素,然后成对,直到其中一个列表到达其结尾,这就是[(x,y)| x <- xs, y <-ys]合并在一起的方式。

答案 2 :(得分:0)

这将是我的糟糕回答

kk :: ( a -> b -> c) -> (a,b) -> c 
kk f (x,y) = f x y 

combineFunk :: (a ->  b -> c) -> [a] -> [b] -> [c]
combineFunk f xs ys = [cs | (a,b)  <- zip xs ys  , let  cs = kk f (a,b) ]