【问题标题】:Linear types in OCamlOCaml 中的线性类型
【发布时间】:2013-03-25 16:52:27
【问题描述】:

Rust 具有线性类型系统。有什么(好的)方法可以在 OCaml 中模拟这个吗?例如,当使用 ocaml-lua 时,我想确保仅当 Lua 处于特定状态(堆栈顶部的表等)时才调用某些函数。

编辑:这是最近一篇关于与该问题相关的资源多态性的论文:https://arxiv.org/abs/1803.02796

编辑 2:还有许多关于 OCaml 中会话类型的文章,包括提供一些语法糖的语法扩展。

【问题讨论】:

  • 您可以使用 monads 在 monadic 绑定中隐藏“线性”类型处理,并且仅将 monadic 类型导出为抽象。
  • 模拟是什么意思?运行时检查?
  • 不,静态的。 “模拟”是指使用现有类型系统来实现(接近)线性类型系统。
  • 这里有一些关于依赖类型的有趣研究:okmij.org/ftp/Computation/lightweight-dependent-typing.html

标签: ocaml linear-types


【解决方案1】:

正如 John Rivers 所建议的,您可以使用一元样式来表示 以隐藏线性约束的方式“有效”计算 效果 API。下面是一个示例,其中类型 ('a, 'st) t 是 用于表示使用文件句柄(其标识为 隐含/不言而喻,以保证它不能被复制),将 产生'a 类型的结果并将文件句柄保留在状态 'st(幻像类型为“打开”或“关闭”)。你必须使用 monad¹的run 实际做任何事情,它的类型确保 文件句柄在使用后正确关闭。

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 的 monadic regions 示例。

您可能还对研究编程语言感兴趣 Mezzo,旨在 是 ML 的变体,具有更细粒度的状态控制(以及相关的 有效的模式)通过线性打字规则与分离 资源。请注意,目前这只是一个研究实验,不是 实际上是针对用户的。 ATS 也是相关的, 虽然最终不像 ML。 Rust 实际上可能是一个合理的 这些实验的“实用”对应物。

¹:它实际上不是一个 monad,因为它没有 return/unit 组合子,但关键是要像 monadic bind 运算符那样强制类型控制排序。不过,它可能有一个map

【讨论】:

  • 能否请您也提供一个使用示例?我还没有真正得到这个单子的东西。 :P
  • @OlleHärstedt:最后有一个用法示例(let test ...)。还是你想要别的?
  • 出于好奇,是否可以定义一个与堆栈状态完全对应的幻像类型?在 Lua 和 OCaml/C 之间进行通信时,我们使用堆栈:Lua.newtable state;; (* Put new table on stack *) Lua.pushstring state "index";; (* Put table index on stack *) 所以幻像类型现在类似于 [string, table]
  • 如何交替读取 2 个文件的行并将它们写入第三个文件?
猜你喜欢
  • 1970-01-01
  • 2013-12-01
  • 2013-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 2012-09-29
相关资源
最近更新 更多