获取两个流并在 OCaml 中组合它们

Taking two streams and combining them in OCaml

我想以递增的顺序获取两个整数流,并将它们组合成一个不包含重复项且应按递增顺序排列的流。我按以下方式定义了流的功能:

type 'a susp = Susp of (unit -> 'a)
let force (Susp f) = f()

type 'a str =  {hd : 'a ; tl : ('a str) susp }

let merge s1 s2 = (* must implement *)

第一个函数通过将计算包装在函数中来暂停计算,第二个函数计算函数并向我提供计算结果。

我想模仿你如何组合列表的逻辑,即匹配两个列表并检查哪些元素更大、更小或相等,然后追加(cons)整数以使结果列表排序.

但是,我知道我当然不能只用流来做这件事,因为我不能像列表一样遍历它,所以我想我需要逐个整数进行比较,然后暂停计算并继续这样做构建结果流。

然而,我对如何实现这样的逻辑有点不知所措,假设我应该这样做,所以如果有人能指出我正确的方向,那就太好了。

谢谢!

如果输入的序列是有序的,合并列表和序列之间没有太大区别。考虑以下列表合并函数:


let rec merge s t =
  match s, t with
  | x :: s , [] | [], x :: s -> x :: s
  | [], [] -> s
  | x :: s', y :: t' ->
    if x < y then
      x :: (merge s' t)
    else if x = y then
      x :: (merge s' t')
    else
       y :: (merge s t')

此函数仅使用列表的两个属性:

  • 能够将潜在的第一个元素与列表的其余部分分开
  • 将元素添加到列表前面的能力

这表明我们可以将此函数重写为签名上的仿函数

module type seq = sig
  type 'a t
 
  (* if the seq is non-empty we split the seq into head and tail *)
  val next: 'a t -> ('a * 'a t) option

  (* add back to the front *)
  val cons: 'a -> 'a t -> 'a t
end

那么如果我们把list上的模式匹配换成调用next,cons操作换成调用cons,前面的函数就变成了:

module Merge(Any_seq: seq ) = struct

  open Any_seq

  let rec merge s t =
    match next s, next t with
    | Some(x,s), None | None, Some (x,s) ->
      cons x s
    | None, None -> s
    | Some (x,s'), Some (y,t') ->
      if x < y then
        cons x (merge s' t)
      else if x = y then
        cons x (merge s' t')
      else
        cons y (merge s t')

end

然后,对于列表,我们的实现是:

module List_core = struct
  type 'a t = 'a list
  let cons = List.cons
  let next = function
  | [] -> None
  | a :: q -> Some(a,q)
end
module List_implem = Merge(List_core)

可以用

测试
let test = List_implem.merge [1;5;6] [2;4;9]

为您的流类型实现相同的功能只是为流编写一个类似的 Stream_core 模块的问题。