Skip to content

Instantly share code, notes, and snippets.

@lambdahands
Last active November 6, 2015 09:47
Show Gist options
  • Save lambdahands/6d9d025a85c8ca16f0d7 to your computer and use it in GitHub Desktop.
Save lambdahands/6d9d025a85c8ca16f0d7 to your computer and use it in GitHub Desktop.
Object Algebras in OCaml
(*
* An OCaml implementation of object algebras, inspired from this article by Oleksandr Manzyuk:
* https://oleksandrmanzyuk.wordpress.com/2014/06/18/from-object-algebras-to-finally-tagless-interpreters-2/
*)
module ObjectAlgebras = struct
(* We technically don't need these interfaces;
* added here to compare between the Java implementation *)
type 'a expAlg = < lit : int -> 'a; add : 'a -> 'a -> 'a >
type 'a mulAlg = < mul : 'a -> 'a -> 'a >
(* Eval implementations *)
class eval init = object
method eval: int = init
end
class evalexp = object
method lit n = new eval n
method add (x: eval) (y: eval) = new eval (x#eval + y#eval)
end
class evalmul = object
inherit evalexp
method mul (x: eval) (y: eval) = new eval (x#eval * y#eval)
end
(* View implementations *)
class view init = object
method view: string = init
end
class viewexp = object
method lit n = new view (string_of_int n)
method add (x: view) (y: view) =
let s = "(" ^ x#view ^ " + " ^ y#view ^ ")"
in new view s
end
class viewmul = object
inherit viewexp
method mul (x: view) (y: view) =
let s = "(" ^ x#view ^ " * " ^ y#view ^ ")"
in new view s
end
let () =
(* exp instances*)
let e1 f = f#add (f#lit 10) (f#lit 10) in
let v1 = (new evalexp |> e1)#eval in
let s1 = (new viewexp |> e1)#view in
(* mul instances*)
let e2 f = f#mul (f#lit 10) (f#lit 10) in
let v2 = (new evalmul |> e2)#eval in
let s2 = (new viewmul |> e2)#view
in Printf.printf "%s = %d\n" s1 v1; (* (10 + 10) = 20 *)
Printf.printf "%s = %d\n" s2 v2 (* (10 * 10) = 100 *)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment