Advertisement
xavierm02

Untitled

Jul 17th, 2015
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 8.50 KB | None | 0 0
  1. (*(* Let's say I have those types *)
  2.  
  3. type ('input, 'output, 'datatype, 'make_argument) polymorphic_finite_partial_function_implementation =
  4.   {
  5.     make: 'make_argument -> 'datatype;
  6.     set: 'input -> 'output -> 'datatype -> 'datatype;
  7.     unset: 'input -> 'datatype -> 'datatype;
  8.     get: 'input -> 'datatype -> 'output option
  9.   }
  10.  
  11. type ('input, 'output, 'datatype, 'make_argument) t =
  12.   {
  13.     data: 'datatype;
  14.     implementation: ('input, 'output, 'datatype, 'make_argument) polymorphic_finite_partial_function_implementation
  15.   }
  16.  
  17. (* Where (i, o, d, a) t represents i -> o
  18. (d is just the datatype used to actually represent it and a is the type of what is needed to initialize an element of d)
  19.  
  20. And I have two "subtypes":
  21. *)
  22.  
  23. (* 'input1 * 'input2 -> 'output *)
  24. type ('input, 'output, 'datatype, 'make_argument) uncurried_t = ('input, 'output, 'datatype, 'make_argument) t
  25. constraint 'input = 'input1 * 'input2
  26.  
  27. (* 'input1 -> 'input2 -> 'output *)
  28. type ('input, 'output, 'datatype, 'make_argument) curried_t = ('input, 'output, 'datatype, 'make_argument) t
  29. constraint 'output = 'input2 -> 'output2
  30.  
  31. (*  And for some random reason, I would like to build a function between those types
  32.  
  33. uncurry : ('input1 -> 'input2 -> 'output) -> ('input1 * 'input2 -> 'output)
  34.  
  35. [ mainly because ('input1 -> 'input2 -> 'output) is more efficient for everything but
  36. ('input1 * 'input2 -> 'output) is as efficient and easier to use for some others ]
  37.  
  38. The problem is that only have access to the implementation of ('input1 -> 'input2 -> 'output) and have no
  39. way of getting the implementation of ('input2 -> 'output) [unless I'm lucky and I get an element of ('input2 -> 'output) by
  40. applying an element of ('input1 -> 'input2 -> 'output) to an element of ('input1), but in some cases I can't].
  41.  
  42. A possible solution would be to add something to the implementation that returns the implementation of the codomain but then
  43. it becomes weird for non-function types. The only thing I thought of was to replace non-function types x by unit -> x when they
  44. appear as a codomain to allow implementing that additionnal method but it feels weird.
  45.  
  46. Is there something else I could do? My only constraint is that operations on t must works on all types that represent functions
  47.  
  48. The rest of this file contains a version of what I want (functionality-wise, not convenience-wise) that uses modules that works
  49. (or at least compiles) and the same thing in the version where implementations are carried arround as records
  50. (for which I can't finish the uncurry function *)
  51.  
  52.  
  53.  
  54. *)
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61. open Batteries
  62. open Map
  63.  
  64. module type POLYMORPHIC_FINITE_PARTIAL_FUNCTION = sig
  65.   type ('input, 'output) t
  66.  
  67.   type ('input, 'output) make_argument
  68.  
  69.   val make : ('input, 'output) make_argument -> ('input, 'output) t
  70.  
  71.   val set : 'input -> 'output -> ('input, 'output) t -> ('input, 'output) t
  72.  
  73.   val unset : 'input -> ('input, 'output) t -> ('input, 'output) t
  74.  
  75.   val get : 'input -> ('input, 'output) t -> 'output option
  76.  
  77.   val set_option : 'input -> 'output option -> ('input, 'output) t -> ('input, 'output) t
  78. end
  79.  
  80. module FromConstant :  POLYMORPHIC_FINITE_PARTIAL_FUNCTION = struct
  81.   type ('input, 'output) t = 'output option
  82.  
  83.   type ('input, 'output) make_argument = unit
  84.  
  85.   let make x = None
  86.  
  87.   let set _ output _ = Some output
  88.  
  89.   let unset _ _ = None
  90.  
  91.   let set_option _ output_option _ = output_option
  92.  
  93.   let get _ f = f
  94. end
  95.  
  96. module FromPMap : POLYMORPHIC_FINITE_PARTIAL_FUNCTION = struct
  97.   type ('input, 'output) t = ('input, 'output) PMap.t
  98.  
  99.   type ('input, 'output) make_argument = unit
  100.  
  101.   let make () =
  102.     PMap.empty
  103.  
  104.   let set input output f =
  105.     PMap.add input output f
  106.  
  107.   let unset input f =
  108.     PMap.remove input f
  109.  
  110.   let set_option input output_option f =
  111.     match output_option with
  112.     | None -> unset input f
  113.     | Some output -> set input output f
  114.  
  115.   let get input f =
  116.     try
  117.       Some (PMap.find input f)
  118.     with
  119.     | Not_found -> None
  120. end
  121.  
  122. module Uncurry (Outer : POLYMORPHIC_FINITE_PARTIAL_FUNCTION) (Inner : POLYMORPHIC_FINITE_PARTIAL_FUNCTION) = struct
  123.   type ('input, 'output) t = ('outer_input, ('inner_input, 'output) Inner.t) Outer.t * ('inner_input, 'output) Inner.make_argument
  124.   constraint 'input = 'inner_input * 'outer_input
  125.  
  126.   type ('input, 'output) make_argument =  ('outer_input, ('inner_input, 'output) Inner.t) Outer.make_argument * ('inner_input, 'output) Inner.make_argument
  127.   constraint 'input = 'inner_input * 'outer_input
  128.  
  129.   let make (outer_make_argument, inner_make_argument) =
  130.     (Outer.make outer_make_argument, inner_make_argument)
  131.  
  132.   let set (outer_input, inner_input) output (outer_f, inner_make_argument) =
  133.     let inner_f =
  134.       match Outer.get outer_input outer_f with
  135.       | None -> Inner.make inner_make_argument
  136.       | Some inner_f' -> inner_f'
  137.     in
  138.     let new_inner_f = Inner.set inner_input output inner_f in
  139.     let new_outer_f = Outer.set outer_input new_inner_f in
  140.     (new_outer_f, inner_make_argument)
  141.  
  142.   let unset (outer_input, inner_input) (outer_f, inner_make_argument) =
  143.     match Outer.get outer_input outer_f with
  144.     | None -> (outer_f, inner_make_argument)
  145.     | Some inner_f ->
  146.       let new_inner_f = Inner.unset inner_input inner_f in
  147.       let new_outer_f = Outer.set outer_input new_inner_f outer_f in
  148.       (new_outer_f, inner_make_argument)
  149.  
  150.   let get (outer_input, inner_input) (outer_f, _) =
  151.     match Outer.get outer_input outer_f with
  152.     | None -> None
  153.     | Some inner_f -> Inner.get inner_input inner_f
  154.  
  155. end
  156.  
  157.  
  158.  
  159.  
  160.  
  161. (* Nearly perfect but one case doesn't work because there is no way to access the implementation of
  162.   B -> C from the implementation of A -> B -> C *)
  163.  
  164. type ('input, 'output, 'datatype) polymorphic_finite_partial_function_implementation =
  165.   {
  166.     make: unit -> 'datatype;
  167.     set: 'input -> 'output -> 'datatype -> 'datatype;
  168.     unset: 'input -> 'datatype -> 'datatype;
  169.     get: 'input -> 'datatype -> 'output option
  170.   }
  171.  
  172. type ('input, 'output, 'datatype) t =
  173.   {
  174.     data: 'datatype;
  175.     implementation: ('input, 'output, 'datatype) polymorphic_finite_partial_function_implementation
  176.   }
  177.  
  178. let set input output f =
  179.   {
  180.     data = f.implementation.set input output f.data;
  181.     implementation = f.implementation
  182.   }
  183.  
  184. let unset input f =
  185.   {
  186.     data = f.implementation.unset input f.data;
  187.     implementation = f.implementation
  188.   }
  189.  
  190. let set_option input output_option f =
  191.   match output_option with
  192.   | None -> unset input f
  193.   | Some output -> set input output f
  194.  
  195. let get input f =
  196.   f.implementation.get input f.data
  197.  
  198. let pmap_implementation =
  199.   let make' () =
  200.     PMap.empty
  201.   in
  202.   let set' input output f =
  203.     PMap.add input output f
  204.   in
  205.   let unset' input f =
  206.     PMap.remove input f
  207.   in
  208.   let get' input f =
  209.     try
  210.       Some (PMap.find input f)
  211.     with
  212.     | Not_found -> None
  213.   in
  214.   {
  215.     make = make';
  216.     set = set';
  217.     unset = unset';
  218.     get = get'
  219.   }
  220.  
  221. type ('input, 'output, 'datatype) uncurried_t = ('input, 'output, 'datatype) t
  222. constraint 'input = 'input1 * 'input2
  223.  
  224. type ('input, 'output, 'datatype) curried_t = ('input, 'output, 'datatype) t
  225. constraint 'output = 'input2 -> 'output2
  226.  
  227. let uncurry (f : ('outer_input, 'inner_input -> 'output, 'datatype) curried_t) : ('outer_input * 'inner_input, 'output, 'datatype) t =
  228.   let make' () =
  229.       f.implementation.make ()
  230.   in
  231.   let set' (outer_input, inner_input) output outer_f =
  232.     let inner_f =
  233.       match get outer_input outer_f with
  234.       | None -> failwith "TODO" (* INNER_IMPLEMENTATION.make inner_make_argument,
  235.                                 and I can't access it because the only element of type outer_input I have doesn't
  236.                                 give back a value when the function is applied to it *)
  237.       | Some inner_f' -> inner_f'
  238.     in
  239.     let new_inner_f = set inner_input output inner_f in
  240.     let new_outer_f = set outer_input new_inner_f outer_f in
  241.     new_outer_f
  242.   in
  243.   let unset' (outer_input, inner_input) outer_f =
  244.     match get outer_input outer_f with
  245.     | None -> outer_f
  246.     | Some inner_f ->
  247.       let new_inner_f = unset inner_input inner_f in
  248.       let new_outer_f = set outer_input new_inner_f outer_f in
  249.       new_outer_f
  250.   in
  251.   let get' (outer_input, inner_input) outer_f =
  252.     match get outer_input outer_f with
  253.     | None -> None
  254.     | Some inner_f -> get inner_input inner_f
  255.   in
  256.   let implementation' =
  257.     {
  258.       make = make';
  259.       set = set';
  260.       unset = unset';
  261.       get = get'
  262.     }
  263.   in
  264.   {
  265.     data = f.data;
  266.     implementation = implementation'
  267.   }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement