2015-10-16 86 views
1

你通常对纯函数式编程中的列表做什么?函数式编程中列表上常见的高阶基元是什么? (地图,折叠和?)

显然我们有map f [x0; x1; x2]其中产生[f x0; f x1; f x2]fold f acc [x0; x1; x2]其产生f (f (f acc x0) x1) x2)

对于map,在呼叫到f之间没有信息传输;对于fold,由f产生的所有信息通过累加器acc在下次调用中被重新注入。

我也看到了类似的东西是flatmap通过串接时map f返回f列表以及适用谓词的名单中的所有元素for_all产生的名单,但这些都是mapfold只是特殊情况。

我能想到的东西中间会产生一个名单,但也迭代(OCaml的语法)期间保持累加器:

let rec map_acc ~f acc = function 
    | [] -> [] 
    | x::xs -> let (y, acc) = f x acc in y::(map_acc ~f acc xs) 

问题:

  • map_acc函数式编程通常概念?
  • 如果是,它的规范名称是什么?
  • 是否在标准库中实现?
  • 其他常用的高阶函数是什么?

注:

这里是map_acc用于产生运行总和的示例:

let sums xs = map_acc ~f:(fun x sum -> let sum = sum + x in (sum, sum)) 0 xs 

而且sums [3; 5; 6; 9]产生[3; 8; 14; 23]。授予sums可以使用fold和精心设计的累加器来实现,但使用mac_acc更简单。

+2

关于'sums'的最后评论,技术上*所有*都可以实现为'fold',但它会变得非常难看。此外,我很惊讶'过滤器'没有出现在你的名单上。 – BlackVegetable

+0

这不是函数式编程中的常用概念(对我来说当然是)。 –

回答

2

map_acc看起来像一个稍微一般scan_left:下几个函数式语言的标准库不同的名字

let scan_left f init list = 
    let _, xs = List.fold_left 
     (fun (acc, coll) elt -> 
     let acc' = f acc elt in acc', acc'::coll) 
     (init, []) list in 
    List.rev xs 

scan_left (+) 0 [3; 5; 6; 9] => [3; 8; 14; 23] 

此功能和变种出现,虽然没有OCaml的。

这些功能都不值得被称为基元。