Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 程序程序员的功能代码片段列表?_Haskell_F#_Ocaml_Functional Programming_Code Snippets - Fatal编程技术网

Haskell 程序程序员的功能代码片段列表?

Haskell 程序程序员的功能代码片段列表?,haskell,f#,ocaml,functional-programming,code-snippets,Haskell,F#,Ocaml,Functional Programming,Code Snippets,有时,我仍然无法将过程代码转换为函数代码 是否有映射到过程性习惯用法/代码段的功能性习惯用法/代码段列表 编辑 由于这些代码片段似乎没有一个集中的网站,我将把它变成一个社区wiki。请在这里粘贴任何程序->功能片段。哦,现在这是一个漂亮的问题。以下是一些或一些cloe: for循环可以替换为迭代器 stripped_list=[line.strip()表示行中的行列表] for循环可以替换为apply、map或filter 地图(大写,[“句子”,“片段]) ['句子','片段'] 具有函数

有时,我仍然无法将过程代码转换为函数代码

是否有映射到过程性习惯用法/代码段的功能性习惯用法/代码段列表

编辑


由于这些代码片段似乎没有一个集中的网站,我将把它变成一个社区wiki。请在这里粘贴任何程序->功能片段。

哦,现在这是一个漂亮的问题。以下是一些或一些cloe:

  • for循环可以替换为迭代器

    stripped_list=[line.strip()表示行中的行列表]

  • for循环可以替换为apply、map或filter

    地图(大写,[“句子”,“片段]) ['句子','片段']

  • 具有函数组合的嵌套for循环

  • 尾部递归代替循环

  • 替代for循环的生成器表达式

    sum(x*x表示范围(10)内的x))

旧的家庭作业问题:

功能

是一种典型的命令式风格,带有赋值和循环。编写一个等效函数f-functional,它不使用命令特性begin(排序)、while(转到)和set(赋值)。您可以使用任意数量的“helper函数”,只要它们是使用let或letrec定义的,而不是在顶层

一个解决方案:

; The idea is simple: 
; Use parameter passing for binding the values 
; of the variables and recursion instead of iteration. 
;
; For those who like theory this is the main argument for proving 
; that recursive functions (LISP, lambda calculus) have the same 
; computational power as any imperative programming language. 

(define f-functional (y) 
  (letrec (
     (f-helper (lambda (x y)
                  (if (p x y) 
                     (f-helper (g x y) y)
                     (h x y)))))
     (f-helper e y)))

; Notice that y in f-helper is invariant.  Therefore, we can rewrite
; f-helper without y as follows.

(define f-functional (y) 
  (letrec (
     (f-helper (lambda (x)
                  (if (p x y) 
                     (f-helper (g x y))
                     (h x y)))))
     (f-helper e)))

; This is not the only solution, though I think it is one of the 
; nicer ones.
(自编)

当我第一次在OCaml/F#中访问break/continue时,可以说,它让我陷入了一个(无限)循环,因为不存在这样的东西!在OCaml中,可以使用异常来中断循环,因为它们非常便宜,但在F#(In.NET)中,开销非常高,对于“正常”流控制不有用

这是在不久前使用排序算法时出现的(以消磨时间),该算法大量使用repeat/till和break。我突然想到,递归尾部调用函数可以实现完全相同的结果,而可读性只会略有下降。因此,我抛弃了“可变bDone”和“whilenotBDONE”,并尝试在没有这些命令结构的情况下编写代码。下面只提取循环部分,并展示如何使用tailcalls编写repeat/until、do/while、while/do、break/continue和测试中间样式的代码。所有这些似乎都以与传统F#“while”语句完全相同的速度运行,但您的里程数可能会有所不同(某些平台可能无法正确执行tailcall,因此可能会在修补之前叠加故障)。最后是以两种样式编写的(糟糕的)排序算法,用于比较

让我们从一个“do/while”循环开始,用传统的F-命令式风格,然后看看函数的变化,它既提供了相同类型的循环,也提供了不同的语义,比如while/DO,重复/直到中间测试,甚至中断/继续(没有单元格…嗯,工作流!) 少了单子的休息是怎么回事?好的,只需引入一个返回“unit”的条件表达式,如下所示:

let funBreak() =
    let rec loop() =
        let x = g()
        if x > N then ()    (*break*)
        else
            f()
            loop()
    loop()
继续怎么样?好吧,这只是另一个循环调用!首先,使用语法拐杖:

let funBreakContinue() =
    let break' () = ()
    let rec continue' () =
        let x = g()
        if   x > N then break'()
        elif x % 2 = 0 then
            f(); f(); f();
            continue'()
        else
            f()
            continue'()
    continue'()
let funBreakContinue'() =
    let rec loop () =
        let x = g()
        if   x > N then ()
        elif x % 2 = 0 then
            f(); f(); f();
            loop()
        else
            f()
            loop ()
    loop()
然后再没有(丑陋的)语法拐杖:

let funBreakContinue() =
    let break' () = ()
    let rec continue' () =
        let x = g()
        if   x > N then break'()
        elif x % 2 = 0 then
            f(); f(); f();
            continue'()
        else
            f()
            continue'()
    continue'()
let funBreakContinue'() =
    let rec loop () =
        let x = g()
        if   x > N then ()
        elif x % 2 = 0 then
            f(); f(); f();
            loop()
        else
            f()
            loop ()
    loop()
容易极了

这些循环形式的一个很好的结果是,可以更容易地发现和实现循环中的状态。例如,冒泡排序会在整个数组上不断循环,在找到不合适的值时交换这些值。它跟踪通过阵列是否产生任何交换。如果不是,则每个值必须位于正确的位置,以便排序可以终止。作为优化,每次通过数组时,数组中的最后一个值都会被排序到正确的位置。因此,循环可以缩短一次通过。大多数算法检查交换并在每次有交换时更新“bModified”标志。然而,一旦第一次互换完成,就不需要进行该转让;这已经设置为真了

下面是实现冒泡排序的F#代码(是的,冒泡排序是一种糟糕的算法;快速排序)。最后是不改变状态的强制执行;它会为每个exchange更新bModified标志。有趣的是,强制解决方案在小型阵列上速度更快,而在大型阵列上速度仅慢一到两个百分点。(不过,这是一个很好的例子)

let inline sort2 f i j(a:'a数组)=
让i'=a[i]
设j'=a[j]
如果f i'j'>0那么

a、 [i]折叠是一个非常有趣的函数,它是许多函数算法的核心。假设我们要添加列表中的所有元素。在过程代码中,通常会创建一个累加器变量并将其设置为0,然后遍历列表并按项递增累加器

在Ocaml中,您可以使用fold以功能性方式执行相同的操作:

List.fold_left (+) 0 [1; 2; 3];;
- : int = 6
例如,使用fold,您可以计算列表中的字数,并同时连接它们:

List.fold_left (fun (count, concat) e -> (count + 1, concat ^ e)) (0, "") ["a"; "b"; "c"];;
- : int * string = (3, "abc")
折叠的另一个有用用途是将向量复制到集合中。由于Ocaml中的集合是不可变的,因此实际上需要为列表中的每个项目创建一个新集合,其中包含上一个集合和该新项目

module Int = struct type t = int let compare = compare end;;
module IntSet = Set.Make(Int);;

let s = List.fold_left (fun set e -> IntSet.add e set) IntSet.empty [1; 2; 3];;
val s : IntSet.t = <abstr>

IntSet.elements s;;
- : IntSet.elt list = [1; 2; 3]
module Int=struct type t=Int let compare=compare end;;
模块IntSet=Set.Make(Int);;
让s=List.fold_left(乐趣集e->IntSet.add e set)IntSet.empty[1;2;3];;

val s:IntSet.t=

PLEAC项目几乎正是以这一点为目标——用其他语言实现perl cookbook中的所有示例。这里是ocaml版本的链接(这是三个100%完成的版本之一)

Snip第二个应该从
map(str.upper,
开始,因为upper是str类的一个方法:str.upper.应该是社区wiki-没有“答案”就其本身而言?@Anthony,我希望有一个网站,但如果没有,那么我会创建这个。看起来你创建这个社区太快了-请查看pleac-o
let inline sort2 f i j (a:'a array) =
    let i' = a.[ i ]
    let j' = a.[ j ]
    if f i' j' > 0 then
        a.[ i ] <- j'
        a.[ j ] <- i'

let bubble f (xs:'a array) =
    if xs.Length = 0
    then ()

    let rec modified i endix =
        if i = endix then
            unmodified 0 (endix-1)
        else
            let j = i+1
            sort2 f i j xs
            modified j endix
    and unmodified i endix =
        if i = endix then
            ()
        else
            let j = i+1
            let i' = xs.[ i ]
            let j' = xs.[ j ]
            if f i' j' > 0 then
                xs.[ i ] <- j'
                xs.[ j ] <- i'
                modified j endix
            else
                unmodified j endix
    in unmodified 0 (xs.Length-1)

let bubble_imperitive f (xs:'a array) =
    let mutable bModified = true
    let mutable endix = xs.Length - 1
    while bModified do
        bModified <- false
        endix <- endix - 1
        for i in 0..endix do
            let j = i+1
            let i' = xs.[ i ]
            let j' = xs.[ j ]
            if f i' j' > 0 then
                xs.[ i ] <- j'
                xs.[ j ] <- i'
                bModified <- true
        done
    done
List.fold_left (+) 0 [1; 2; 3];;
- : int = 6
List.fold_left (fun (count, concat) e -> (count + 1, concat ^ e)) (0, "") ["a"; "b"; "c"];;
- : int * string = (3, "abc")
module Int = struct type t = int let compare = compare end;;
module IntSet = Set.Make(Int);;

let s = List.fold_left (fun set e -> IntSet.add e set) IntSet.empty [1; 2; 3];;
val s : IntSet.t = <abstr>

IntSet.elements s;;
- : IntSet.elt list = [1; 2; 3]