5
votes

Excuse me if this is quite basic, I'm new to functional programming and F#.

I have to create a function that takes a list of tuples (string*int) and return a list of tuples (string *int)

So basically I want to apply some functions to each tuple in pairList and return a list of tuples.

I am guessing I could do this through a recursive function.

I have the following code so far:

let rec aFunction (pairList:List<string*int>): List<string*int> =
  match pairList with
  | [] -> []
  | head :: tail ->  [fst head,snd (someFunc1 (someFunc2 (fst head,snd head)))]

This basically just apply the various functions to only the head of the list and return me a list of tuple.

In order to get it working for the whole list I tried the following:

| head :: tail ->  [fst head,snd (someFunc1 (someFunc2 (fst head,snd head)));aFunction tail]

But I get the following error :

This expression was expected to have type string * int but here has type List < string * int >

3

3 Answers

5
votes

This function does in fact exist already - it is called List.map.

To analyse your error, when you do [a;b] a and b need to have the same type.

What you wanted was to use the concatenation operator :: like this:

| head :: tail ->  (fst head,snd (someFunc1 (someFunc2 (fst head,snd head)))) :: (aFunction tail)

but you can actually make this neater by pattern matching in a better way

| (a,b) :: tail ->  (a,snd (someFunc1 (someFunc2 (a,b)))) :: (aFunction tail)
5
votes

John Palmers answer is more than good enough, but I would probably also go all the way and do about the following for clarity and readability:

let someFunc1 = id //just to make it compile
let someFunc2 = id //just to make it compile

let someFunc3 = someFunc2 >> someFunc1 >> snd
let someFunc4 head = fst head, someFunc3 head 

let rec aFunction (pairList:List<string*int>): List<string*int> =
  match pairList with
  | [] -> []
  | head :: tail -> someFunc4 head :: (aFunction tail)
4
votes

And here's the List.map option John alluded to:

// make a helper function that converts a single tuple
let convertTuple (s, i) =
  let i1 = (s, i) |> someFunc2 |> someFunc1 |> snd // pipeline operator helps remove parens
  s, i1

// now you can simply
let aFunction pairList = List.map convertTuple pairList

// or even more simply using pointfree syntax:
let aFunction = List.map convertTuple

Note the above aFunction is so simple you may not even want a special function for it: it's perhaps more intuitive just to type out List.map convertTuple myList in full everywhere you need it.

That's the general idea with F#; start with some helpers that are the minimal transforms you want to make, and then build them up into bigger things using the combinators.