Vic*_*let 5 dependencies ocaml module friend
我目前有两个"层"模块,代表数据库中的标识符 - 数据关系.
所述第一层限定标识符类型,例如IdUser.t
或IdPost.t
,而第二层定义了数据类型,例如User.t
或Post.t
.我需要在第二层的模块之前编译第一层的所有模块,因为Post.t
必须保留IdUser.t
其作者并User.t
保留IdPost.t
他访问的最后五个帖子.
现在,IdUser.t
提供只应该被使用的功能User.t
,例如将变换IdUser.t
为IdUser.current
:的能力.出于安全原因,此变换必须仅由函数执行User.check_password
.由于IdUser
和User
是独立的模块,我需要定义这些功能作为公共职能,依靠约定来避免调用它们以外的任何位置User
,这是相当脏.对称情况发生在IdPost.mine
:
module IdUser : sig
type t
type current
val current_of_t : t -> current (* <--- Should not be public! *)
end = struct
type t = string
type current = string
let current_of_t x = x
end
module IdPost : sig
type t
type mine
val mine_of_t : t -> mine (* <--- Should not be public! *)
end = struct
type t = string
type mine = string
let mine_of_t x = x
end
module Post : sig
(* Should not "see" IdUser.current_of_t but needs IdPost.mine_of_t *)
val is_mine : IdUser.current -> IdPost.t -> IdPost.mine
end
module User : sig
(* Should not "see" IdPost.mine_of_t but needs IdUser.current_of_t *)
val check_password : IdUser.t -> password:string -> IdUser.current
end
Run Code Online (Sandbox Code Playgroud)
有没有一种定义current_of_t : t -> current
函数的方法IdUser
,只能从模块内调用User
?
编辑:这是一对模块的简化示例,但有一个明显的解决方案,对于一对不能推广到多对,我需要为多对解决这个 - 大约18对,实际上...所以,我将它扩展为两对的一个例子.
小智 3
IdUser
事实上,存在主义类型也是如此:因为User
存在一种
可以让IdUser.current
公众IdUser.t
接受的类型。有几种方法可以对此进行编码:User
如果静态管理依赖关系就足够了,则可以按照 Gasche 所示进行函式化,或者如果需要更多活力,则可以使用一流的模块或对象。
我将进一步研究 Gasche 的示例,为了方便起见,使用私有类型缩写,并展示如何利用半透明性来避免过度私有化实现类型。首先,这可能是一个限制,我想声明一个持久的 ADT IDs
:
(* File id.ml *)
module type ID = sig
type t
type current = private t
end
module type PERSISTENT_ID = sig
include ID
val persist : t -> current
end
Run Code Online (Sandbox Code Playgroud)
有了这个,我可以Post
使用 s 的具体类型来定义ID
s 的类型,但使用 ADT 来强制执行与持久性相关的业务规则:
(* File post.ml *)
module Post
(UID : ID with type t = string)
(PID : PERSISTENT_ID with type t = int)
: sig
val is_mine : UID.current -> PID.t -> PID.current
end = struct
let is_mine uid pid =
if (uid : UID.current :> UID.t) = "me" && pid = 0
then PID.persist pid
else failwith "is_mine"
end
Run Code Online (Sandbox Code Playgroud)
与 s 相同User
:
(* File user.ml *)
module User
(UID : PERSISTENT_ID with type t = string)
: sig
val check_password : UID.t -> password:string -> UID.current
end = struct
let check_password uid ~password =
if uid = "scott" && password = "tiger"
then UID.persist uid
else failwith "check_password"
end
Run Code Online (Sandbox Code Playgroud)
请注意,在这两种情况下,我都使用具体但私有的ID
类型。将所有内容结合在一起是一个简单的问题,实际上定义ID
ADT 及其持久性规则:
module IdUser = struct
type t = string
type current = string
let persist x = x
end
module IdPost = struct
type t = int
type current = int
let persist x = x
end
module MyUser = User (IdUser)
module MyPost = Post (IdUser) (IdPost)
Run Code Online (Sandbox Code Playgroud)
此时,为了完全解耦依赖关系,您可能需要签名,USER
并且POST
可以从该模块导出签名,但添加它们很简单。
归档时间: |
|
查看次数: |
562 次 |
最近记录: |