gpt4 book ai didi

types - OCaml : type constraints in signatures

转载 作者:行者123 更新时间:2023-12-04 18:48:09 25 4
gpt4 key购买 nike

在我的代码中,我有一个 数据库访问上下文 提供基本读/写操作,称为 CouchDB.ctx .然后,我的应用程序中的各种模块使用附加功能扩展该类,例如 Async.ctx .

我正在实现 Cache包裹在 Source 周围的模块模块。 Cache模块函数采用上下文参数并操作数据库。一些调用然后被转发到 Source模块连同上下文。

我需要按照以下方式定义一个仿函数:

module CouchDB = struct
class ctx = object
method get : string -> string option monad
method put : string -> string -> unit monad
end
end

module AsyncDB = struct
class ctx = object
inherit CouchDB.ctx
method delay : 'a. float -> (ctx -> 'a monad) -> 'a monad
end
end

module type SOURCE = sig
class ctx = #CouchDB.ctx (* <-- incorrect *)
type source
val get : source -> ctx -> string monad
end

module Cache = functor(S:SOURCE) -> struct
class ctx = S.ctx
type source = S.source
let get source ctx =
bind (ctx # get source) (function
| Some cache -> return cache
| None ->
bind (S.get source ctx)
(fun data -> bind (ctx # put source data)
(fun () -> return data))
end

module SomeSource = struct
class ctx = AsyncDB.ctx
type source = string
let get s ctx =
ctx # async 300 (some_long_computation s)
end

module SomeCache = Cache(SomeSource)

问题是我无法表达 Source 使用的上下文这一事实。模块应该是 CouchDB.ctx 的子类型.上面的代码返回错误:
A type variable is unbound in this type declaration.
In type #CouchDB.ctx as 'a the variable 'a is unbound

如何表达这种类型约束?

最佳答案

[过时的...

您可以获得的最接近的是将签名定义为:

module type SOURCE = sig
type 'a ctx = 'a constraint 'a = #CouchDB.ctx
type source
val get : source -> 'a ctx -> string
end

但是,当然,您也可以只写:
module type SOURCE = sig
type source
val get : source -> #CouchDB.ctx -> string
end

编辑:请注意,OCaml 对对象使用结构类型。这意味着即使您想要,您也无法获得比上述更多的限制。它甚至不将参数限制为 get成为 CouchDB.ctx 的实例或派生类——任何具有(至少)相同方法的对象都是兼容的。即使你写
  val get : source -> CouchDB.ctx -> string 

您可以传递任何具有相同方法的对象。类型 CouchDB.ctx只是一个特定结构对象类型的缩写,恰好匹配由同名类生成的对象。它不限于那些。只是为了确定:这被认为是一个功能。

======]

编辑 2:通过扩展示例,我现在看到了您想要什么以及为什么。不幸的是,这在 OCaml 中是不可能的。您将需要部分抽象类型。也就是说,您需要能够编写
module type SOURCE = sig
type ctx < CouchDB.ctx
...
end

这在 OCaml 中不可用。但是,如果您愿意在签名中提供明确的向上转换,则可以接近:
module type SOURCE = sig
type ctx
val up : ctx -> CouchDB.ctx
type source = string
val get : source -> ctx -> string monad
end

然后,在 Cache ,您必须替换出现的 ctx#get(S.up ctx)#get ,同样适用于 ctx#put .
module Cache = functor (S:SOURCE) -> struct
type ctx = S.ctx
type source = S.source
let get source ctx =
bind ((S.up ctx)#get source) ...
end

module SomeSource = struct
type ctx = AsyncDB.ctx
let up ctx = (ctx : ctx :> CouchDB.ctx)
type source = string
let get s ctx = ...
end

module SomeCache = Cache (SomeSource)

请注意,我还制作了 type source = string签名透明 SOURCE .没有它,我看不到 ctx#get source可以在 Cache 中进行类型检查仿函数。

关于types - OCaml : type constraints in signatures,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10588382/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com