Rust有一个线性类型系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。
编辑:这是最近一篇关于与该问题相关的资源多态性的论文:https ://arxiv.org/abs/1803.02796
编辑 2:还有许多关于 OCaml 中会话类型的文章,包括提供一些语法糖的语法扩展。
Rust有一个线性类型系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。
编辑:这是最近一篇关于与该问题相关的资源多态性的论文:https ://arxiv.org/abs/1803.02796
编辑 2:还有许多关于 OCaml 中会话类型的文章,包括提供一些语法糖的语法扩展。
正如 John Rivers 所建议的,您可以使用单子样式来表示“有效”计算,从而隐藏效果 API 中的线性约束。下面是一个示例,其中类型('a, 'st) t
用于表示使用文件句柄的计算(其身份是隐式/不言而喻的,以保证它不能被复制),将产生类型的结果'a
并将文件句柄保持在状态
'st
(幻像类型“打开”或“关闭”)。您必须使用run
monad¹ 来实际做任何事情,它的类型确保文件句柄在使用后正确关闭。
module File : sig
type ('a, 'st) t
type open_st = Open
type close_st = Close
val bind : ('a, 's1) t -> ('a -> ('b, 's2) t) -> ('b, 's2) t
val open_ : string -> (unit, open_st) t
val read : (string, open_st) t
val close : (unit, close_st) t
val run : ('a, close_st) t -> 'a
end = struct
type ('a, 'st) t = unit -> 'a
type open_st = Open
type close_st = Close
let run m = m ()
let bind m f = fun () ->
let x = run m in
run (f x)
let close = fun () ->
print_endline "[lib] close"
let read = fun () ->
let result = "toto" in
print_endline ("[lib] read " ^ result);
result
let open_ path = fun () ->
print_endline ("[lib] open " ^ path)
end
let test =
let open File in
let (>>=) = bind in
run begin
open_ "/tmp/foo" >>= fun () ->
read >>= fun content ->
print_endline ("[user] read " ^ content);
close
end
当然,这只是为了让您体验 API 的风格。有关更严重的用途,请参阅 Oleg 的单子区域示例。
您可能还对研究编程语言 Mezzo感兴趣,该语言旨在成为 ML 的一种变体,通过具有分离资源的线性类型规则对状态(和相关的有效模式)进行更细粒度的控制。请注意,目前这只是一项研究实验,并非真正针对用户。ATS也是相关的,尽管最终不像 ML。Rust 实际上可能是这些实验的合理“实用”对应物。
¹:它实际上不是一个单子,因为它没有return
/unit
组合子,但关键是像单子运算符一样强制类型控制排序bind
。不过,它可能有一个map
。