John Riversが提案しているように、モナディックスタイルを使用して、エフェクトAPIの線形制約を非表示にする方法で「効果的な」計算を表すことができます。以下は('a, 'st) t
、ファイルハンドル(複製できないことを保証するためにIDが暗黙的/暗黙的)を使用して計算を表すために型が使用され、型の結果を生成し'a
、ファイルハンドルを状態
'st
(ファントム型)のままにする1つの例です。 「オープン」または「クローズ」のいずれか)。実際に何かを行うには、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のスタイルを味わうことだけを目的としています。より深刻な使用法については、オレグのモナディックリージョンの例を参照してください。
また、研究プログラミング言語Mezzoに興味があるかもしれません
。これは、分離されたリソースを使用した線形型付けの分野を通じて、状態(および関連する効果的なパターン)をよりきめ細かく制御するMLの変形を目指しています。これは現時点での調査実験であり、実際にはユーザーを対象としたものではないことに注意してください。ATSも関連性がありますが、最終的にはMLに似ていません。さびは、実際にはこれらの実験の合理的な「実用的な」対応物である可能性があります。
return
¹: /コンビネータがないため、実際にはモナドではありませんが、重要なのは、モナド演算子unit
のように型制御シーケンスを強制することです。bind
しかし、それは持つことができmap
ます。