Поскольку список понимание обычно дает декартово произведение, вы также можете попробовать ZipList из Control.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 дает вам некоторое объяснение о том, как его использовать, получайте удовольствие!
Кстати, вы можете использовать голый список в приведенном выше примере, который дает вам декартово произведение:
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