Reputation: 121
I'm (very) new to Haskell and I'm trying to solve what I think is a simple problem:
I want to create a list of the Cartesian product of two lists of different types: eg. one contains characters and one contains integers.
['A','B','C']
and the infinite list:
[1..]
I'm trying to get an output where each of my letters is suffixed with a number: eg.
["A1", "B1", "C1", "A2", "B2"..]
I've been attempting this using things I've read online, however I'm struggling. As I understand it, I want to convert my integer list to a string using 'show'. My code is below:
combinations xs cs = (,) <$> xs (show <$> cs)
Where xs and cs are passed in my function as ['A','B','C'] and [1..] respectively.
However I receive this error:
Couldn't match expected type ‘[String] -> [a0]’
with actual type ‘[Char]’
I'd really appreciate any ideas as I've been struggling for a while.
Thanks
Upvotes: 0
Views: 185
Reputation: 91837
(,) <$> xs (show <$> cs)
parses as
(,) <$> (xs (show <$> cs))
Note that here you are calling xs
as a function, with show <$> cs
as its argument. That can't be right: xs
is a String!
Since you seem to be trying to program in applicative style, you probably meant to write something of the form
f <$> a <*> b
In your case,
f = (,)
a = xs
b = show <$> cs
So, you meant to write:
(,) <$> xs <*> (show <$> cs)
This is sorta close to what you wanted, but there are a few problems. First, its type is [(Char, String)]
, where you wanted them joined up as strings. That can be fixed by using (:)
instead of (,)
.
Second, since one list is infinite, you need to process that as your "outermost loop" - if it's an inner loop, the fact that it never ends will mean your other loops never progress. When using []
as an Applicative, the "outer loop" is the first thing you map over.
So, we might try:
(,) <$> (show <$> cs) <*> xs
Note I've gone back to (,)
for a moment to highlight something:
Prelude> take 5 $ (,) <$> (show <$> cs) <*> xs
[("1",'A'),("1",'B'),("1",'C'),("2",'A'),("2",'B')]
Now we get the pairs you want, but (:)
won't work on them anymore because they're in the wrong order. So, you need to use a different function, one like (:)
but which takes its arguments in the other order. Happily, it is easy to produce such a function: it's simply flip (:)
:
Prelude> take 5 $ (flip (:)) <$> (show <$> cs) <*> xs
["A1","B1","C1","A2","B2"]
Upvotes: 2