2013-03-25 96 views
5

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

+0

您可以使用monad隐藏monadic绑定中的“线性”类型处理,并且仅将monadic类型导出为抽象类型。 – 2013-03-25 17:39:34

+0

你是什么意思模拟?运行时检查? – didierc 2013-03-25 20:59:42

+0

不,静态的。对于“模拟”,我的意思是使用现有的类型系统来实现(接近)线性类型的系统。 – 2013-03-25 22:37:27

回答

7

正如John Rivers所建议的那样,您可以使用monadic风格以某种方式表示 “有效”的计算方式,该方式隐藏了效果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的通过线性打字纪律与分离 资源状态的更细粒度的控制(及相关 effectful模式)的变体。请注意,它现在只是一个研究实验,而不是实际针对用户的 。 ATS也是相关的, 虽然最终不像ML样。 Rust实际上可能是这些实验的“实用”对应物。

¹:它实际上不是单子,因为它没有return/unit组合子,但重点是强制类型控制的排序,因为单子bind操作符。不过,它可能有map

+0

您能否提供一个使用示例?我还没有真正得到这个monad的东西。 :P – 2013-03-26 16:00:34

+0

@OlleHärstedt:最后有一个用法示例('let test ...')。或者你想要别的东西吗? – gasche 2013-03-26 18:14:56

+0

对不起,没有看到!这对我来说很神奇,谢谢! :) – 2013-03-26 18:38:43