Justin Tyler
Justin Tyler

Reputation: 225

Haskell Invert Pair

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)]

Upvotes: 6

Views: 7927

Answers (3)

asm
asm

Reputation: 8898

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.

Upvotes: 5

Luis Casillas
Luis Casillas

Reputation: 30237

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:

  1. How to split a problem into small, reusable pieces.
  2. The standard library functions offered by the language.
  3. How to use recursion to write small, reusable functions like the ones in the standard library.

In this case, we can split the problem into:

  1. Inverting an individual tuple.
  2. Applying a function to all elements of a list, and collecting the list of results.

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

Upvotes: 5

Petr
Petr

Reputation: 63409

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.)

Upvotes: 18

Related Questions