Guest User

Untitled

a guest
Jun 23rd, 2023
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 4.32 KB | None | 0 0
  1. open! Core
  2.  
  3. module type Monoid = sig
  4.   type t
  5.  
  6.   val t : t Type_equal.Id.t
  7.   val unit : t
  8.   val op : t -> t -> t
  9.   val eq : t -> t -> bool
  10. end
  11. module type S = Monoid
  12.  
  13. module Monoid = struct
  14.   type 'a t = (module Monoid with type t = 'a)
  15.  
  16.   let same (type a1 a2) (monoid1 : a1 t) (monoid2 : a2 t) =
  17.     let module Monoid1 = (val monoid1) in
  18.     let module Monoid2 = (val monoid2) in
  19.     Type_equal.Id.same_witness Monoid1.t Monoid2.t
  20.   ;;
  21. end
  22.  
  23. module MonoidElement = struct
  24.   type t = Constructor : 'a Monoid.t * 'a -> t
  25.  
  26.   (* (* Alternative definition *)
  27.   module type MonoidElement = sig
  28.     module Monoid : Monoid
  29.     val element : Monoid.t
  30.   end
  31.   type t = (module MonoidElement)
  32.   *)
  33.  
  34.   let is_unit (Constructor (monoid, element)) =
  35.     let module Monoid1 = (val monoid) in
  36.     Monoid1.eq element Monoid1.unit
  37.   ;;
  38.  
  39.   let eq (Constructor (monoid1, element1)) (Constructor (monoid2, element2)) =
  40.     let module Monoid1 = (val monoid1) in
  41.     let module Monoid2 = (val monoid2) in
  42.     match Type_equal.Id.same_witness Monoid1.t Monoid2.t with
  43.     | None -> false
  44.     | Some eq_wit ->
  45.       let element1_in_2 = Type_equal.conv eq_wit element1 in
  46.       Monoid2.eq element1_in_2 element2
  47.   ;;
  48. end
  49.  
  50. module IntMonoid = struct
  51.   type t = int
  52.  
  53.   let t = Type_equal.Id.create ~name:"IntMonoid.t" [%sexp_of: _]
  54.   let unit = 0
  55.   let op = ( + )
  56.   let eq = Int.equal
  57. end
  58.  
  59. let int_monoid : int Monoid.t = (module IntMonoid)
  60.  
  61. module StrMonoid = struct
  62.   type t = string
  63.  
  64.   let t = Type_equal.Id.create ~name:"StrMonoid.t" [%sexp_of: _]
  65.   let unit = "0"
  66.   let op = ( ^ )
  67.   let eq = String.equal
  68. end
  69.  
  70. let str_monoid : string Monoid.t = (module StrMonoid)
  71.  
  72. module DList = struct
  73.   type 'a t = 'a list
  74.  
  75.   let append l1 l2 = List.append l1 l2
  76.  
  77.   type 'a first_and_rest =
  78.     | NoFirst
  79.     | FirstAndRest of 'a * 'a t
  80.  
  81.   type 'a rest_and_last =
  82.     | NoLast
  83.     | RestAndLast of 'a t * 'a
  84.  
  85.   let uncons_first l : 'a first_and_rest =
  86.     match l with
  87.     | [] -> NoFirst
  88.     | h :: t -> FirstAndRest (h, t)
  89.   ;;
  90.  
  91.   let uncons_last l =
  92.     match List.rev l with
  93.     | [] -> NoLast
  94.     | h :: t -> RestAndLast (t, h)
  95.   ;;
  96. end
  97.  
  98. module FreeProductOfAllMonoids = struct
  99.   type t = MonoidElement.t DList.t
  100.   (* Invariants : there are no neutral elements, and consecutive elements live in distinct monoids *)
  101.  
  102.   let unit = []
  103.  
  104.   type reduction_result =
  105.     | Irreducible
  106.     | Reduced of MonoidElement.t
  107.  
  108.   let maybe_reduce_aux (type a1 a2) (monoid1, element1) (monoid2, element2) =
  109.     let module Monoid1 = (val monoid1 : Monoid with type t = a1) in
  110.     let module Monoid2 = (val monoid2 : Monoid with type t = a2) in
  111.     let element1_is_unit = Monoid1.eq element1 Monoid1.unit in
  112.     let element2_is_unit = Monoid2.eq element2 Monoid2.unit in
  113.     let same_monoid = Type_equal.Id.same_witness Monoid1.t Monoid2.t in
  114.     match element1_is_unit, element2_is_unit, same_monoid with
  115.     | true, _, _ -> Reduced (MonoidElement.Constructor (monoid2, element2))
  116.     | _, true, _ -> Reduced (MonoidElement.Constructor (monoid1, element1))
  117.     | _, _, Some eq ->
  118.       let element1_in_2 = Type_equal.conv eq element1 in
  119.       let element = Monoid2.op element1_in_2 element2 in
  120.       Reduced (MonoidElement.Constructor (monoid2, element))
  121.     | false, false, None -> Irreducible
  122.   ;;
  123.  
  124.   let maybe_reduce x y =
  125.     match x, y with
  126.     | ( MonoidElement.Constructor (monoid1, element1)
  127.       , MonoidElement.Constructor (monoid2, element2) ) ->
  128.       maybe_reduce_aux (monoid1, element1) (monoid2, element2)
  129.   ;;
  130.  
  131.   let rec op (t1 : t) (t2 : t) =
  132.     match DList.uncons_last t1, DList.uncons_first t2 with
  133.     | NoLast, _ -> t2
  134.     | _, NoFirst -> t1
  135.     | RestAndLast (es1, e1), FirstAndRest (e2, es2) ->
  136.       (match maybe_reduce e1 e2 with
  137.        | Irreducible -> DList.append t1 t2
  138.        | Reduced e ->
  139.          let ( $ ) = op in
  140.          es1 $ [ e ] $ es2)
  141.   ;;
  142.  
  143.   let rec eq t1 t2 = List.equal MonoidElement.eq t1 t2
  144. end
  145.  
  146. let test () =
  147.   let int i = [ MonoidElement.Constructor (int_monoid, i) ] in
  148.   let str s = [ MonoidElement.Constructor (str_monoid, s) ] in
  149.   let ( $ ) = FreeProductOfAllMonoids.op in
  150.   let ok_str =
  151.     if FreeProductOfAllMonoids.eq
  152.          (str "a" $ int 1 $ int 1 $ int (-2) $ str "b")
  153.          (str "ab")
  154.     then "OK"
  155.     else "Not OK"
  156.   in
  157.   print_endline ok_str
  158. ;;
  159.  
Advertisement
Add Comment
Please, Sign In to add comment