Functional programming 如何使用LinkedList样式和就地修改实现堆栈?

Functional programming 如何使用LinkedList样式和就地修改实现堆栈?,functional-programming,ocaml,Functional Programming,Ocaml,在Java中,很容易实现linkedlist风格的stack 我们只需创建一个内部类项,它有两个属性:值和下一个 那么我们总是第一个项目 然后,当按下按钮时,我们创建一个新的项目,让它的下一个点指向当前的第一个项目,然后让当前的第一个项目成为新的项目 可以对pop执行类似操作 但是我怎样才能在OCaml中做到这一点呢?尤其是当我们需要就地修改(可变)时 我之所以说mutable,是因为普通的pop只弹出值,而不是新堆栈。OCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学

Java
中,很容易实现
linkedlist
风格的
stack

我们只需创建一个内部类
,它有两个属性:
下一个

那么我们总是第一个项目

然后,当按下
按钮时,我们创建一个新的
项目
,让它的下一个点指向当前的
第一个项目
,然后让当前的
第一个项目
成为新的
项目

可以对
pop
执行类似操作


但是我怎样才能在OCaml中做到这一点呢?尤其是当我们需要
就地修改
可变
)时


我之所以说
mutable
,是因为普通的
pop
只弹出值,而不是新堆栈。

OCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学会没有它(IMHO)。它的好处惊人地大,成本惊人地小

尽管如此,下面是一个可变堆栈类型的快速草图

type 'a stack = { mutable stack: 'a list }

let new_stack () = { stack = [] }

let is_empty stack = stack.stack = []

let push x stack = stack.stack <- x :: stack.stack

let pop stack =
    match stack.stack with
    | [] -> raise Not_found
    | x :: xs -> stack.stack <- xs; x
type'a stack={mutable stack:'a list}
让new_stack()={stack=[]}
let is_empty stack=stack.stack=[]
让push x stack=stack.stack raise未找到

|x::xs->stack.stackOCaml是一种多范式语言。使用可变数据一点也不困难。但是真正值得努力去学会没有它(IMHO)。它的好处惊人地大,成本惊人地小

尽管如此,下面是一个可变堆栈类型的快速草图

type 'a stack = { mutable stack: 'a list }

let new_stack () = { stack = [] }

let is_empty stack = stack.stack = []

let push x stack = stack.stack <- x :: stack.stack

let pop stack =
    match stack.stack with
    | [] -> raise Not_found
    | x :: xs -> stack.stack <- xs; x
type'a stack={mutable stack:'a list}
让new_stack()={stack=[]}
let is_empty stack=stack.stack=[]
让push x stack=stack.stack raise未找到

|为了补充Jeffrey的优秀答案,我想在 在这种情况下,实现持久接口和 堆栈数据结构的可变接口,如可变 接口可以构建在持久接口之上

module Impl = struct
  type 'a t = 'a list
  let empty = []
  let is_empty = function [] -> true | _ -> false
  let push x stack = x::stack

  let pop = function
    | [] -> raise Not_found
    | x::xs -> (x,xs)
end

module PersistentStack : sig
  type +'a t
  val empty : 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> 'a t
  val pop : 'a t -> 'a * 'a t
end = struct
  include Impl
end

module MutableStack : sig
  type 'a t
  val new_stack : unit -> 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> unit
  val pop : 'a t -> 'a
end = struct
  type 'a t = 'a Impl.t ref
  let new_stack () = ref Impl.empty
  let is_empty stack = Impl.is_empty !stack
  let push x stack = (stack := Impl.push x !stack)
  let pop stack =
    let (x, xs) = Impl.pop !stack in
    stack := xs;
    x
end

为了补充杰弗里出色的回答,我想在 在这种情况下,实现持久接口和 堆栈数据结构的可变接口,如可变 接口可以构建在持久接口之上

module Impl = struct
  type 'a t = 'a list
  let empty = []
  let is_empty = function [] -> true | _ -> false
  let push x stack = x::stack

  let pop = function
    | [] -> raise Not_found
    | x::xs -> (x,xs)
end

module PersistentStack : sig
  type +'a t
  val empty : 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> 'a t
  val pop : 'a t -> 'a * 'a t
end = struct
  include Impl
end

module MutableStack : sig
  type 'a t
  val new_stack : unit -> 'a t
  val is_empty : 'a t -> bool
  val push : 'a -> 'a t -> unit
  val pop : 'a t -> 'a
end = struct
  type 'a t = 'a Impl.t ref
  let new_stack () = ref Impl.empty
  let is_empty stack = Impl.is_empty !stack
  let push x stack = (stack := Impl.push x !stack)
  let pop stack =
    let (x, xs) = Impl.pop !stack in
    stack := xs;
    x
end

您能否详细说明堆栈数据结构需要哪些功能?此外,如果您希望能够替换堆栈中的元素,只需使用
ref
类型的堆栈实现(如回答中所述)。您能否详细说明堆栈数据结构需要哪些功能?另外,如果您想替换堆栈中的元素,只需使用堆栈实现(如答案中所述)使用
ref
类型。我只是添加了
mutable
来表示某事是可变的?我只是添加了
mutable
来表示某事是可变的?你不能这样将任何持久性数据结构转换为可变结构吗?@rgrinberg:与直接就地数据结构相比,这种情况并不常见,这样做时只有恒定的开销实现(以数组为例)。Jeffrey的代码在将一个完全正确的普适实现隐藏在易变性的面纱下方面是值得注意的,我明确地将这两个方面分开了?你不能用这种方式将任何持久数据结构转换为可变数据结构吗?@rgrinberg:与直接就地实现(以数组为例)相比,这样做的开销通常不是恒定的。Jeffrey的代码在将一个完全正确的普适实现隐藏在易变性的面纱下方面是值得注意的,我明确地将这两个方面分开了?