Отбрасывание одинакового значения по списку кортежей Haskell

Я хотел бы преобразовать следующий список кортежей

a = [(1,()),(2,())]

во вложенный список кортежей с тем же значением

b = [(False,(1,())),(False,(2,()))]

Использование zip-функции в этом формате

zip [False] a

только дает мне

[(False,(1,()))]

Любые предложения или советы будут очень оценены.

Ответы

Ответ 1

Если вы застегиваете два списка разной длины, вы получаете длину кратчайшего списка.

Вы можете исправить это, нажимая на бесконечно длинный список:

zip (repeat False) a

должен сделать трюк.

Ответ 2

В качестве альтернативы вместо zip вы можете использовать map:

map (\x -> (False, x)) a

Это более целесообразно выразить ваше намерение (на мой взгляд), поскольку вы хотите сделать то же самое для каждого элемента списка. Если вы хотите делать разные вещи для каждого элемента, более подходящим может быть zip или zipWith.

Если вы хотите избежать лямбды, вы можете записать ее без использования с помощью &&& из Control.Arrow:

map (const False &&& id) a

который в основном говорит "примените к входу функции const False и id, а затем постройте кортеж обоих их выходов". Существует расширение TupleSections, которое позволит вам записать это как

map (False,) a

(подсказка @thoferon), но я лично считаю это менее ясным, так как вы должны знать, что расширение включено и обратите внимание на , после False. Вы можете написать это как

map ((,) False) a

без расширения, поскольку (,) действует как функция типа a -> b -> (a, b), а в то время как немного более подробный, он не требует включения языкового расширения.

Ответ 3

В дополнение к другим ответам также можно написать общую функцию для любого Functor, а не только для списков:

strengthL :: Functor f => a -> f b -> f (a, b)
strengthL = fmap . (,)

strengthR :: Functor f => a -> f b -> f (b, a)
strengthR = fmap . flip (,)

Затем strengthL можно применить к False и исходному списку:

Prelude> strengthL False [(1,()),(2,())]
[(False,(1,())),(False,(2,()))]