在使用Array在OCaml中实现Stack时,如何保持多态?

时间:2013-02-21 16:56:49

标签: functional-programming ocaml

我正在使用stackOCaml中实施array

我希望它接受任何类型。这是我实施的一部分,我的问题也是关于它。


type 'a stack = {mutable storage : 'a array; mutable n : int};;
let create () = {storage = Array.make 2 0; n = -1};;

所以,上面,当我定义我的堆栈类型时,它很好。 storage'a array,这是一个接受任何类型的数组。

但是当我实现create函数时,我遇到了问题。如何初始化'a array?我不能,对吧?当我创建它时,我必须给它一个初始值,对吗?


那么如何使用具有多态性的数组创建堆栈?

3 个答案:

答案 0 :(得分:2)

为什么要在OCaml中使用数组实现堆栈?这没有任何意义,这不是C ++或Java。不可变堆栈:

 type 'a stack = Empty | Stack of 'a * 'a stack

 let pop = function
   | [] -> raise (Invalid_argument "empty stack")
   | x :: s -> x, s

 let push x s = x :: s

 let is_empty s = (s = Empty)

可变堆栈:

type 'a stack = 'a list ref

let create () = ref []

let pop s =
  match !s with
    | [] -> raise (Invalid_argument "empty stack")
    | x :: xs -> s := xs ; x

let push x s = (s := x :: !s)

let is_empty s = (!s = [])

P.S。在你声称数组以某种方式变得更快之前,你应该进行测试。

答案 1 :(得分:1)

你可以懒惰地分配数组:

type 'a stack = {mutable storage : 'a array option; mutable n : int}
let create () = {storage = None; n = -1}

然后,您的推送功能将检查堆栈是否已初始化并创建不是。

的数组

但是,更一般地说,我认为你最好用'a list ref来定义你的堆栈。或者甚至更好,使用不可变堆栈,即列表。

答案 2 :(得分:1)

您的storage字段是可变的,因此您可以在不同的时间放置不同的数组。因此,您可以使用一个完全多态的空数组进行初始化(如空列表)。

另一种方法是为storage字段使用选项类型,并在第一次推送操作时创建数组。

我有时会在生产代码中遇到此类问题。我通常最终使用选项类型。

(更好的方法是使用堆栈列表。除非您需要访问除顶部之外的元素,否则该阵列只会造成麻烦并且不会带来任何好处。)

<强>更新

这是一个函数,它返回一个比提供的数组大两倍的数组。为了灵活性,额外的元素不能保证具有任何特定的值(尽管实际上它们只是原始数组的第0个元素的副本)。

let double array =
    let len = Array.length array in
    if len = 0 then array  (* 2 * 0 = 0 *)
    else
        Array.init
            (2 * len)
            (fun x -> if x < len then array.(x) else array.(0))