问题描述
我想按升序排列两个整数流,并将它们组合成一个不包含重复项且应按升序排列的流。我已经通过以下方式定义了流的功能:
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 *)
第一个函数通过将函数包装在函数中来暂停计算,第二个函数对函数求值并向我提供计算结果。
我想模拟如何组合列表的逻辑,即在两个列表上都匹配,并检查哪些元素更大,或更小或相等,然后附加(约束)整数以对结果列表进行排序。 / p>
但是,我知道我当然不能只使用流来完成此操作,因为我无法像列表一样遍历它,所以我认为我需要逐整数进行比较,比较,然后暂停计算并继续这样做以构建产生的流。
但是,我不知如何实现这样的逻辑,假设这是我应该做的事情,因此,如果有人可以向我指出正确的方向,那将是很好的。
谢谢!
解决方法
如果对输入序列进行了排序,则合并列表和序列之间没有太大区别。考虑列表上的以下合并功能:
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
然后,如果我们通过调用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
模块。