我想比较一下我正在研究的游戏AI的两种启发式的性能。一个处理FIFO顺序的元素;另一个是LIFO订单。
目前,代码使用Queue
以FIFO顺序处理元素。在OOP中,Bag
和Stack
都会实现Queue
接口,我会使用Bag.push
和Bag.take
与结构进行交互。然后,我会根据命令行标志的值,将Stack.create ()
或Queue.create ()
的结果分配给类型Bag
的变量。
我知道如何使用抽象类复制OCaml中的类似行为并使用:>
约束类型。但是,我想可能有一种更简洁的方法可以做到这一点,不需要在Queue
和Stack
周围编写包装类。
我试过像
这样的东西module type Bag =
sig
type 'a t
exception Empty
val create : unit -> 'a t
val push : 'a -> 'a t -> unit
val iter : ('a -> unit) -> 'a t -> unit
end
module BagWrapper (B : Bag) =
struct
type 'a t = 'a B.t
let create () = B.create ()
let push a b = B.push a b
let iter a b = B.iter a b
end
module QueueBag = BagWrapper(Queue)
module StackBag = BagWrapper(Stack)
......但我不确定接下来该做什么。想法?
答案 0 :(得分:3)
Bag
模块的值很好,但您也可以这样做
通过简单地定义遍历算法,在更简单的OCaml中
在一个以袋子为参数的仿函数里面。
module type Bag =
sig
type 'a t
exception Empty
val create : unit -> 'a t
val push : 'a -> 'a t -> unit
val pop : 'a t -> 'a
val iter : ('a -> unit) -> 'a t -> unit
end
module Traversal (B : Bag) = struct
let go start children f =
let to_visit = B.create () in
B.push start to_visit;
try while true do
let next = B.pop to_visit in
f next;
let mark neighbor = B.push neighbor to_visit in
List.iter mark (children next);
done with B.Empty -> ()
end;;
(* note that "BagWrapper" is useless here as the existing modules
fit the Bag interface perfectly, there is no need for a middle
layer *)
module StackTraversal = Traversal(Stack)
module QueueTraversal = Traversal(Queue)
(* ... if foo then StackTraversal.go else QueueTraversal.go ... *)
答案 1 :(得分:2)
好的,所以你要写
let module Bag = if use_queue then QueueBag else StackBag in
some algorithm
但OCaml不允许你这样做..
let m = if use_queue then (module QueueBag : Bag) else (module StackBag : Bag) in
let module Bag = (val m : Bag) in
这看起来相当冗长,幸运的是,较新的OCaml版本允许您在这种情况下删除某些类型的注释。