【发布时间】:2022-10-30 18:52:11
【问题描述】:
module type Cont_map = sig
type t
type key
type value = key (* values are the same type as keys *)
val empty : t
val lookup : key -> t -> value option
val insert : key -> value -> t -> t
val remove : key -> t -> t * value option
val lub_key : key -> t -> key option
val glb_key : key -> t -> key option
val interpolated_lookup : key -> t -> value option
end
module Cont_map (Key : Interp with type t = float) : Cont_map = struct
type t =
| Leaf
| Branch of Key.t * Key.t * t * t
type key = Key.t
type value = key
let empty = Leaf
let rec lookup k dmap =
match dmap with
| Leaf -> None
| Branch (kk, vv, l, r) -> if k < kk then lookup k l else if k > kk then lookup k r else Some(vv)
let rec insert kk vv dmap =
match dmap with
| Leaf -> Branch (kk, vv, Leaf, Leaf)
| Branch (k, v, l, r) ->
if kk < k then Branch (k, v, insert kk vv l, r)
else if kk = k then Branch (k, vv, l, r)
else Branch (k, v, l, insert kk vv r)
let remove kk dmap =
let rec max_key (d: t) =
match d with
| Leaf -> None
| Branch (key, value, _, right) ->
match right with
| Leaf -> Some(key, value)
| Branch (_, _, _, _) -> max_key(right)
in
let rec remove_internal kk map =
match map with
| Leaf -> remove_internal kk map
| Branch (k, v, l, r) ->
if kk < k then Branch (k, v, remove_internal kk l, r)
else if kk = k then
match max_key(l) with
| Some(key, value) -> Branch (key, value, remove_internal key l, r)
| None -> r
else Branch (k, v, l, remove_internal kk r)
in
match lookup kk dmap with
| None -> (dmap, None)
| Some(v) -> (remove_internal kk dmap, Some(v))
let rec lub_key kk map =
let rec max_key (d: t) =
match d with
| Leaf -> None
| Branch (key, _, _, right) ->
match right with
| Leaf -> Some(key)
| Branch (_, _, _, _) -> max_key(right)
in
match map with
| Leaf -> None
| Branch (k, _, l, r) -> if kk < k then
match max_key(l) with
| None -> Some(k)
| Some(kkk) -> if kkk < kk then Some(k) else lub_key kk l
else if kk = k then Some(k) else lub_key kk r
let rec glb_key kk map =
let rec min_key (d: t) =
match d with
| Leaf -> None
| Branch (key, _, left, _) ->
match left with
| Leaf -> Some(key)
| Branch (_, _, _, _) -> min_key(left)
in
match map with
| Leaf -> None
| Branch (k, _, l, r) -> if kk < k then glb_key kk l else if kk = k then Some(k)
else match min_key(r) with
| None -> Some(k)
| Some(kkk) -> if kkk <= kk then glb_key kk r else Some(k)
let interpolated_lookup kk map =
match lub_key kk map with
| None -> None
| Some(rk) -> match glb_key kk map with
| None -> None
| Some(lk) -> match lookup lk map, lookup rk map with
| Some(lv), Some(rv) -> Some(Key.interpolate (lk, lv) (rk, rv) kk)
| _ -> failwith "Can't reach here"
end
module Float_cont_map = Cont_map (Float_interp)
以上是我在一个名为 abstraction.ml 的文件中的代码
open Core;;
open OUnit2;;
module M = Abstraction.Cont_map(Abstraction.Float_interp);;
let empty = M.empty
let d1 = M.(Branch (1.0, 1.0, Leaf, Branch (2.0, 2.0, Leaf, Branch (3.0, 3.0, Leaf, Branch (4.0, 4.0, Leaf, Leaf)))))
这是我的名为 tests.ml 的测试文件
(test
(name tests)
(libraries
core
ounit2
abstraction
))
这是我在测试目录中的沙丘文件。
但是,它称之为“未绑定构造函数分支”。在下面的代码中,我写道:
let test_lookup _ =
assert_equal None @@ (M.lookup 1. empty);
assert_equal (Some(1.0)) @@ (M.lookup 1. d1)
它没有说 M.lookup 未绑定值,但它说预期的 M.value 类型但获得浮动。
【问题讨论】:
-
模块签名隐藏省略的信息。在这里,您暴露了类型
t的存在,但隐藏了它的定义。因此Branch和Leaf构造函数在M之外不可见。如果你需要它们,你不应该隐藏它们。 -
风格小问题:
assert_equal None @@ (M.lookup 1. empty)与写作assert_equal None (M.lookup 1. empty)相同。当您编写assert_equal None @@ M.lookup 1. empty时,@@运算符会派发股息。
标签: module constructor ocaml