Wondering if I could get some help writing this function. I am trying to create a function that inverts each "pair" in the list.
module Invert where
invert :: [(a,b)] -> [(b,a)]
invert [(a,b)] = [(b,a)]
When I enter invert [(3,1) (4,1) (5,1)]
... it is supposed to give me [(1,3) (1,4) (1,5)
... But it gives me...
*Invert> [(3,1) (4,1) (5,1)]
<interactive>:2:2:
The function `(3, 1)' is applied to two arguments,
but its type `(t0, t1)' has none
In the expression: (3, 1) (4, 1) (5, 1)
In the expression: [(3, 1) (4, 1) (5, 1)]
In an equation for `it': it = [(3, 1) (4, 1) (5, 1)]
Since lists are recursive data structures, you have to process a list recursively in order to swap all its elements, or use some higher order function that does the processing for you. If you define
invert [(a,b)] = [(b,a)]
it will only convert single-element lists, all other inputs will fail with an error!
Try to think about the input invert
gets: It's either an empty list, or a non-empty lists. In the case of a non-empty list, you can swap the first element and convert the rest recursively.
(If you don't want to invert invert
yourself, just use
invert = map swap
where swap
is from Data.Tuple
.)
So you want to map a function over the list that's of type (a, b) -> (b, a)
. The function (,)
has type b -> a -> (b,a)
. So if we flip it, we get a -> b -> (b, a)
. Now if we uncurry that, we get (a, b) -> (b, a)
:
invert = map (uncurry $ flip (,))
E.g.
> map (uncurry $ flip (,)) [(1, "a"), (2, "b")]
[("a",1),("b",2)]
As an aside, your patten matching doesn't match what you want. The definition
invert [(a,b)] = [(b,a)]
says "match a list with a single tuple in it". If you have a list with multiple tuples, the match will fail. Also, as Josh Lee pointed out, you need commas between tuples in your list.
Best way to solve this: split it into smaller problems, and either find library functions that solve those, or write your own. I always tell beginners that this is a superior exercise than trying to write a function like invert
in just one part, because you should be learning the following three things:
In this case, we can split the problem into:
The second one is just the common map
function on lists, which comes with the standard library. You could try writing your own version of it; this sort of thing is always a good exercise for a beginner:
map :: (a -> b) -> [a] -> [b]
map f [] = ...
map f (x:xs) = ...
The first, as Petr points out, is the swap
function from Data.Tuple
. But we can write our own easily:
swap :: (a, b) -> (b, a)
swap (a, b) = (b, a)
And now, of course:
invert :: [(a, b)] -> [(b, a)]
invert = map swap
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With