Guest User

Untitled

a guest
Jun 22nd, 2023
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 2.84 KB | None | 0 0
  1. module type Monoid = sig
  2.   type t
  3.  
  4.   val unit : t
  5.   val op : t -> t -> t
  6.   val eq : t -> t -> bool
  7.   val uid : int (* For testing equality of monoids *)
  8. end
  9.  
  10. module type MonoidElem = sig
  11.   module Monoid : Monoid
  12.  
  13.   val elem : Monoid.t
  14. end
  15.  
  16. type monoid_elem = (module MonoidElem)
  17.  
  18. module type MonoidWithPacker = sig
  19.   include Monoid
  20.  
  21.   val pack : t -> monoid_elem
  22. end
  23.  
  24. module AddPacker (M : Monoid) : MonoidWithPacker with type t = M.t = struct
  25.   include M
  26.  
  27.   let pack t =
  28.     let module Elem = struct
  29.       module Monoid = M
  30.  
  31.       let elem = t
  32.     end
  33.     in
  34.     (module Elem : MonoidElem)
  35.   ;;
  36. end
  37.  
  38. module IntMonoid = AddPacker (struct
  39.   type t = int
  40.  
  41.   let unit = 0
  42.   let op = ( + )
  43.   let eq t1 t2 = t1 = t2
  44.   let uid = Hashtbl.hash "IntMonoid"
  45. end)
  46.  
  47. module StrMonoid = AddPacker (struct
  48.   type t = string
  49.  
  50.   let unit = "0"
  51.   let op = ( ^ )
  52.   let eq t1 t2 = t1 = t2
  53.   let uid = Hashtbl.hash "StrMonoid"
  54. end)
  55.  
  56. module DList = struct
  57.   type 'a t = 'a list
  58.  
  59.   let append l1 l2 = List.append l1 l2
  60.  
  61.   type 'a first_and_rest =
  62.     | NoFirst
  63.     | FirstAndRest of 'a * 'a t
  64.  
  65.   type 'a rest_and_last =
  66.     | NoLast
  67.     | RestAndLast of 'a t * 'a
  68.  
  69.   let uncons_first l : 'a first_and_rest =
  70.     match l with
  71.     | [] -> NoFirst
  72.     | h :: t -> FirstAndRest (h, t)
  73.   ;;
  74.  
  75.   let uncons_last l =
  76.     match List.rev l with
  77.     | [] -> NoLast
  78.     | h :: t -> RestAndLast (t, h)
  79.   ;;
  80. end
  81.  
  82. module FreeProductOfAllMonoids = struct
  83.   type t = monoid_elem DList.t
  84.   (* Invariants : there are no neutral elements, and consecutive elements live in distinct monoids *)
  85.  
  86.   let unit = []
  87.  
  88.   let rec op t1 t2 =
  89.     match DList.uncons_last t1, DList.uncons_first t2 with
  90.     | NoLast, _ -> t2
  91.     | _, NoFirst -> t1
  92.     | RestAndLast (es1, e1), FirstAndRest (e2, es2) ->
  93.       let module E1 = (val e1 : MonoidElem) in
  94.       let module E2 = (val e2 : MonoidElem) in
  95.       if E1.Monoid.uid != E2.Monoid.uid
  96.       then DList.append t1 t2
  97.       else (
  98.         let elem = E1.Monoid.op E1.elem (Obj.magic E2.elem) in
  99.         (* Remove Obj.magic? *)
  100.         if E1.Monoid.eq elem E1.Monoid.unit
  101.         then op es1 es2
  102.         else
  103.           let module E1MonoidWithPacker = AddPacker (E1.Monoid) in
  104.           let e = E1MonoidWithPacker.pack elem in
  105.           op (op es1 [ e ]) es2)
  106.   ;;
  107.  
  108.   let rec eq t1 t2 =
  109.     List.equal (fun e1 e2 ->
  110.       let module E1 = (val e1 : MonoidElem) in
  111.       let module E2 = (val e2 : MonoidElem) in
  112.       E1.Monoid.uid = E2.Monoid.uid && E1.Monoid.eq E1.elem (Obj.magic E2.elem)) t1 t2
  113.   ;;
  114. end
  115.  
  116. let test () =
  117.   let int i = [ IntMonoid.pack i ] in
  118.   let str s = [ StrMonoid.pack s ] in
  119.   let ( $ ) = FreeProductOfAllMonoids.op in
  120.   let ok_str = if (FreeProductOfAllMonoids.eq (str "a" $ int 1 $ int 1 $ int (-2) $ str "b") (str "ab")) then "OK" else "Not OK" in
  121.   print_endline ok_str
  122. ;;
Advertisement
Add Comment
Please, Sign In to add comment