将函数应用于列表中的每个元组

时间:2016-09-22 01:15:01

标签: f#

对不起,如果这是非常基本的,我是函数式编程和F#的新手。

我必须创建一个函数,它接受一个元组列表(string * int)并返回一个元组列表(string * int)

所以基本上我想将一些函数应用于pairList中的每个元组并返回一个元组列表。

我猜我可以通过递归函数来做到这一点。

到目前为止,我有以下代码:

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

这基本上只是将各种函数应用于列表的头部并返回一个元组列表。

为了让它适用于整个列表,我尝试了以下方法:

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

但是我收到以下错误:

此表达式应具有类型字符串* int,但此处具有类型List&lt; string * int&gt;

3 个答案:

答案 0 :(得分:5)

这个功能确实已经存在 - 它被称为List.map

要分析您的错误,当[a;b] ab需要具有相同的类型时。

你想要的是使用这样的连接运算符::

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

但你可以通过更好的模式匹配来实现这个整洁

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

答案 1 :(得分:5)

约翰·帕尔默斯的回答非常好,但为了清晰和可读性,我可能会一路走下去做以下事情:

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)

答案 2 :(得分:4)

这是John提到的List.map选项:

// 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

请注意,上面的aFunction非常简单,您甚至可能不需要特殊的功能:只需在您需要的地方输入List.map convertTuple myList就可以更直观了。

这是F#的总体思路;从一些你想要制作的最小变换的助手开始,然后使用组合器将它们构建成更大的东西。