Подтвердить что ты не робот

Все комбинации элементов из двух списков в Haskell

Учитывая два списка, [a, b] и [c, d], я хотел бы получить следующий результат:

[(a,c), (a,d), (b,c), (b,d)]

Как я могу сделать это в Haskell? Есть ли встроенная функция для этого или я должен сам реализовать ее?

4b9b3361

Ответ 1

[ (x,y) | x<-[a,b], y<-[c,d] ]

На самом деле это не требует никаких дополнительных объяснений, не так ли?

Ответ 2

Аппликационный стиль полностью!

λ> :m + Control.Applicative
λ> (,) <$> ['a','b'] <*> ['c','d']
[('a','c'),('a','d'),('b','c'),('b','d')]

(Я избегал синтаксического сахара String выше, чтобы оставаться рядом с вашим примером.)

Для информации (,) является специальным синтаксисом для функции, которая принимает два аргумента и выдает пару из них:

λ> :t (,)
(,) :: a -> b -> (a, b)

Изменить: как отмечено leftaroundabout в его комментарии, вы также можете использовать liftA2

λ> :m + Control.Applicative
λ> let combine = liftA2 (,)
λ> combine "ab" "cd"
[('a','c'),('a','d'),('b','c'),('b','d')]

Ответ 3

Как вы можете сделать это в императивном псевдокоде?

for each element x in [a,b]:
    for each element y in [c,d]:
        produce (x,y)

В Haskell это записывается как

outerProduct xs ys =
   do
       x <- xs          -- for each x drawn from xs:
       y <- ys          --   for each y drawn from ys:
       return (x,y)     --      produce the (x,y) pair

(следующие комментарии leftaroundabout), это, конечно, очень близко к тому, как определяется liftM2 монадический комбинатор, так что фактически

outerProduct = liftM2 (,)

что совпадает с liftA2 (,), и его различные повторные записи в терминах понятий списка, concatMap function, >>=, <$> и <*>.

Концептуально, хотя это материал Applicative – который будет лучше назван Pairing, – потому что это сопряжение элементов двух "контейнеров" & frasl; "носители" и frasl; независимо от того, что такое Аппликативный Фанктор. Так получилось, что нотация Haskell do работает для монадов, а не (пока) для аппликаций.

В некотором смысле вложенные петли во время компиляции являются Applicative & frasl; Сопрягающие функции; Монады добавляют возможность создавать вложенные петли "на лету" в зависимости от значений, создаваемых "внешним" перечислением.

Ответ 4

Наиболее интуитивно понятным будет использование понимания списков, другие аспекты включают использование аппликативных функторов:

(,) <$> [1,2,3] <*> [4,5,6]

Итак, что это делает?

Помните, что (,) :: a -> b -> (a, b) Принимает два аргумента и возвращает кортеж.

<$> acctally fmap, (<$>) :: Functor f => (a -> b) -> f a -> f b Он выполняет функцию и поднимает ее. В этом случае требуется (,) и поднять его для работы над списком. Таким образом, let x = (,) <$> [1,2] будет генерировать x :: [b -> (Integer, b)], который является списком функций, который принимает b и возвращает кортеж с одним фиксированным аргументом (Integer, b). Наконец, мы применяем его, используя <*>, чтобы сгенерировать все комбинации.

Ответ 5

Использование List List:

s = [a,b]
s' = [c,d]

all_combinations = [(x,y) | x <- s, y <- s']