5Six
5Six

Reputation: 23

Haskell, 2 list to list of tuples pointwise

List1 = [a,b]

List2 = [1,2]

I want the result list to look like this [a1, b2]

Currently i have:

[(v,a) | v <- List1, a <- List2 ]

but that gives [a1, a2, b1, b2]

Upvotes: 2

Views: 241

Answers (3)

Redu
Redu

Reputation: 26161

One other way can also be achieved by the ZipList type which is defined in Control.Applicative to lower the undeterministic approach to a simpler one to one mapping for the List types.

All you need is to import Control.Applicative and use the ZipList data constructor.

λ> getZipList $ (,) <$> ZipList "ab" <*> ZipList [1,2]
[('a',1),('b',2)]

getZipList is an accessor which extracts a proper list from the ZipList type.

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

What you need is zip :: [a] -> [b] -> [(a, b)]. This iterates concurrently over the two lists, and makes 2-tuples for these items.

For example:

Prelude> zip ['a', 'b'] [1,2]
[('a',1),('b',2)]
Prelude> zip [1,4,2,5] "bacd"
[(1,'b'),(4,'a'),(2,'c'),(5,'d')]

zip will stop from the moment that one of the two lists is exhausted. So if one of the lists is infinite, and the other is finite, then the result will be a finite list for example.

You can also make use of the ParallelListComp extension to iterate over collections in parallel in a list comprehension expression:

{-# LANGUAGE ParallelListComp #-}

myzip :: [a] -> [b] -> [(a, b)]
myzip la lb = [(a, b) | a <- la | b <- lb ]

but here it does not make much sense to do that. If you want to do more "complex" zipping, then this extension is probably more useful.

Upvotes: 6

leftaroundabout
leftaroundabout

Reputation: 120711

So, you want a function of type [Char] -> [Int] -> [(Char, Int)]. Let me introduce you to Hoogle:

zip :: [a] -> [b] -> [(a, b)]
base Prelude Data.List GHC.List GHC.OldList, Cabal Distribution.Compat.Prelude.Internal, ghc GhcPrelude
. zip takes two lists and returns a list of corresponding pairs.

zip [1, 2] ['a', 'b'] = [(1, 'a'), (2, 'b')]

If one input list is short, excess elements of the longer list are discarded:

zip [1] ['a', 'b'] = [(1, 'a')]
zip [1, 2] ['a'] = [(1, 'a')]

zip is right-lazy:

zip [] _|_ = []
zip _|_ [] = _|_

zip is capable of list fusion, but it is restricted to its first list argument and its resulting list.
zip :: () => [a] -> [b] -> [(a, b)]
hspec Test.Hspec.Discover, base-compat Prelude.Compat, protolude Protolude, rio RIO.List RIO.Prelude, universum Universum.List.Reexport, dimensional Numeric.Units.Dimensional.Prelude, rebase Rebase.Prelude, ghc-lib-parser GhcPrelude, xmonad-contrib XMonad.Config.Prime, stack Stack.Prelude, LambdaHack Game.LambdaHack.Core.Prelude Game.LambdaHack.Core.Prelude, mixed-types-num Numeric.MixedTypes.PreludeHiding, heart-core Heart.Core.Prelude, intro Intro, hledger-web Hledger.Web.Import, tonalude Tonalude, brittany Language.Haskell.Brittany.Internal.Prelude
zip takes two lists and returns a list of corresponding pairs.

zip [1, 2] ['a', 'b'] = [(1, 'a'), (2, 'b')]

If one input list is short, excess elements of the longer list are discarded:

zip [1] ['a', 'b'] = [(1, 'a')]
zip [1, 2] ['a'] = [(1, 'a')]

zip is right-lazy:

zip [] _|_ = []
zip _|_ [] = _|_

zipExact :: Partial => [a] -> [b] -> [(a, b)]
safe Safe.Exact

zipExact xs ys =
| length xs == length ys = zip xs ys
| otherwise              = error "some message"

zip :: () => [a] -> [b] -> [(a, b)]
numeric-prelude NumericPrelude NumericPrelude.Base, distribution-opensuse OpenSuse.Prelude
zip takes two lists and returns a list of corresponding pairs. If one input list is short, excess elements of the longer list are discarded. zip is right-lazy:

zip [] _|_ = []

(+*+) :: [a] -> [b] -> [(a, b)]
universe-base Data.Universe.Helpers

cartesianProduct (,)
...

The first hit

Upvotes: 3

Related Questions