Skip to content

Instantly share code, notes, and snippets.

@ashalkhakov
Created December 31, 2014 15:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ashalkhakov/5a36de12a2c6750c46ae to your computer and use it in GitHub Desktop.
Save ashalkhakov/5a36de12a2c6750c46ae to your computer and use it in GitHub Desktop.
Encoding monads in ATS2 with function templates
(* ****** ****** *)
// Monads in ATS2 using templates
#include
"share/atspre_define.hats"
(* ****** ****** *)
// the interface
abst@ype M (t@ype)
extern
fun{a:t@ype}
ret : a -> M(a)
extern
fun{a,b:t@ype}
bind : M(a) -> M(b)
symintr >>=
postfix >>=
overload >>= with bind
// we replace the second argument of bind with a function template
// which should allow the ATS compiler to inline aggressively
extern
fun{a,b:t@ype}
bind$cont (x: a): M(b)
(* ****** ****** *)
// one possible implementation
assume M (a:t@ype) = Option a
// an explicit failure function (cf. MonadFail)
fun Mfail {a:t@ype} (): M(a) = None ()
implement{a}
ret (x: a) = Some x
implement{a,b}
bind (x) =
case+ x of
| Some x => bind$cont<a,b>(x)
| None () => None ()
// end of [bind]
// a Maybe monad can be run
fun{a:t@ype} runM (x : M(a)): a =
case+ x of
| None () => exit_errmsg (1, "runM failed!")
| Some x => x
(* ****** ****** *)
// usage example
// this computation doesn't know anything about the internals
// of the implementation of the underlying monad, I think
fun test (x : int): M int =
ret 5 >>= where {implement bind$cont<int,int> (y) =
ret 4 >>= where {implement bind$cont<int,int> (z) =
ret (x + y + z)}}
(* ****** ****** *)
implement main (argc, argv) = let
val comp = test (argc)
// specify the type explicitly
val res = runM<int> (comp)
in
println!("result = ", res);
0
end // end of [main]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment