* [Caml-list] Subtyping (or something like it) @ 2017-11-16 21:46 Reed Wilson 2017-11-17 0:49 ` Yawar Amin 2017-11-17 13:01 ` octachron 0 siblings, 2 replies; 6+ messages in thread From: Reed Wilson @ 2017-11-16 21:46 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 1461 bytes --] A while ago, I made a module which basically extended bigarrays with a few more functions. However, I wanted to have a distinction between read-only and read-write values. The equivalence with bigarrays was irrelevant, so my interface just looked like this: type ro type rw type 'a t val read_only : 'a t -> ro t val get : 'a t -> int -> int val put : rw t -> int -> int -> unit ... Basically, any function that wrote to the type would have to take a "rw t", but anything else would take " 'a t". From what I know about C, "ro" behaves like the "const" qualifier - not water-proof but it catches some of my common mistakes. Now, however, I want to re-export the equivalence between 'a t and bigarrays (mostly for the .{} operator), but also have the read-only/read-write distinction. The problem is that if I write: type 'a t = (int, int8_unsigned_elt, c_layout) Array1.t then OCaml will see that "ro t" and "rw t" are the same and freely let me use "ro t" values in, for example, the "put" function above. To summarize, is there a way to make two types internally represented by bigarrays, the first of which: * can use the bigarray functions (specifically .{} ) * can use all of my new functions and the second type * can't use bigarray functions * can only use a subset of my new functions I don't want to have two different versions of each function that I have to keep track of. Thanks, Reed Wilson -- ç [-- Attachment #2: Type: text/html, Size: 2041 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Caml-list] Subtyping (or something like it) 2017-11-16 21:46 [Caml-list] Subtyping (or something like it) Reed Wilson @ 2017-11-17 0:49 ` Yawar Amin 2017-11-17 2:05 ` Reed Wilson 2017-11-17 13:01 ` octachron 1 sibling, 1 reply; 6+ messages in thread From: Yawar Amin @ 2017-11-17 0:49 UTC (permalink / raw) To: Reed Wilson; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 2137 bytes --] Hi Reed, this is maybe not exactly what you specified, but a `private` type abbreviation ( https://caml.inria.fr/pub/docs/manual-ocaml/extn.html#s-private-types-abbrev ) should work. You'll have to cast your safe array type to a normal bigarray to get the indexing and other operations, e.g.: (my_array : ro t :> (int, int8_unsigned_elt, c_layout) Array1.t).{idx} Also, see http://camltastic.blogspot.ca/2008/05/phantom-types.html for a really cool way to mix phantom types and subtyping. Cheers, Yawar On Thu, Nov 16, 2017 at 4:46 PM, Reed Wilson <cedilla@gmail.com> wrote: > A while ago, I made a module which basically extended bigarrays with a few > more functions. However, I wanted to have a distinction between read-only > and read-write values. The equivalence with bigarrays was irrelevant, so my > interface just looked like this: > > type ro > type rw > type 'a t > val read_only : 'a t -> ro t > val get : 'a t -> int -> int > val put : rw t -> int -> int -> unit > ... > > Basically, any function that wrote to the type would have to take a "rw > t", but anything else would take " 'a t". From what I know about C, "ro" > behaves like the "const" qualifier - not water-proof but it catches some of > my common mistakes. > > Now, however, I want to re-export the equivalence between 'a t and > bigarrays (mostly for the .{} operator), but also have the > read-only/read-write distinction. The problem is that if I write: > type 'a t = (int, int8_unsigned_elt, c_layout) Array1.t > > then OCaml will see that "ro t" and "rw t" are the same and freely let me > use "ro t" values in, for example, the "put" function above. > > To summarize, is there a way to make two types internally represented by > bigarrays, the first of which: > * can use the bigarray functions (specifically .{} ) > * can use all of my new functions > and the second type > * can't use bigarray functions > * can only use a subset of my new functions > > I don't want to have two different versions of each function that I have > to keep track of. > > Thanks, > Reed Wilson > > -- > ç > [-- Attachment #2: Type: text/html, Size: 3339 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Caml-list] Subtyping (or something like it) 2017-11-17 0:49 ` Yawar Amin @ 2017-11-17 2:05 ` Reed Wilson 0 siblings, 0 replies; 6+ messages in thread From: Reed Wilson @ 2017-11-17 2:05 UTC (permalink / raw) To: Yawar Amin; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 2635 bytes --] That looks pretty good! One of the things I tried was to use the private type declaration. However, I failed to take the coercion into account, so I thought they couldn't actually be used as bigarrays. I'd still like to avoid casting to bigarrays, but unless a miracle comes along, I think this is how I'll do it. Thanks! On Thu, Nov 16, 2017 at 4:49 PM, Yawar Amin <yawar.amin@gmail.com> wrote: > Hi Reed, this is maybe not exactly what you specified, but a `private` > type abbreviation ( https://caml.inria.fr/pub/do > cs/manual-ocaml/extn.html#s-private-types-abbrev ) should work. You'll > have to cast your safe array type to a normal bigarray to get the indexing > and other operations, e.g.: > > (my_array : ro t :> (int, int8_unsigned_elt, c_layout) Array1.t).{idx} > > Also, see http://camltastic.blogspot.ca/2008/05/phantom-types.html for a > really cool way to mix phantom types and subtyping. > > Cheers, > > Yawar > > On Thu, Nov 16, 2017 at 4:46 PM, Reed Wilson <cedilla@gmail.com> wrote: > >> A while ago, I made a module which basically extended bigarrays with a >> few more functions. However, I wanted to have a distinction between >> read-only and read-write values. The equivalence with bigarrays was >> irrelevant, so my interface just looked like this: >> >> type ro >> type rw >> type 'a t >> val read_only : 'a t -> ro t >> val get : 'a t -> int -> int >> val put : rw t -> int -> int -> unit >> ... >> >> Basically, any function that wrote to the type would have to take a "rw >> t", but anything else would take " 'a t". From what I know about C, "ro" >> behaves like the "const" qualifier - not water-proof but it catches some of >> my common mistakes. >> >> Now, however, I want to re-export the equivalence between 'a t and >> bigarrays (mostly for the .{} operator), but also have the >> read-only/read-write distinction. The problem is that if I write: >> type 'a t = (int, int8_unsigned_elt, c_layout) Array1.t >> >> then OCaml will see that "ro t" and "rw t" are the same and freely let me >> use "ro t" values in, for example, the "put" function above. >> >> To summarize, is there a way to make two types internally represented by >> bigarrays, the first of which: >> * can use the bigarray functions (specifically .{} ) >> * can use all of my new functions >> and the second type >> * can't use bigarray functions >> * can only use a subset of my new functions >> >> I don't want to have two different versions of each function that I have >> to keep track of. >> >> Thanks, >> Reed Wilson >> >> -- >> ç >> > > -- ç [-- Attachment #2: Type: text/html, Size: 4508 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Caml-list] Subtyping (or something like it) 2017-11-16 21:46 [Caml-list] Subtyping (or something like it) Reed Wilson 2017-11-17 0:49 ` Yawar Amin @ 2017-11-17 13:01 ` octachron 2017-11-17 16:13 ` Reed Wilson 1 sibling, 1 reply; 6+ messages in thread From: octachron @ 2017-11-17 13:01 UTC (permalink / raw) To: caml-list With OCaml 4.06, if what you really want is to have a nice syntax for array indexing, one solution would be to define your own indexing operators: let ( .%{ } ) a k = a.{k} let ( .%{ } <- ) a k x = a.{k} <- x These operators can be used like standard indexing operators let x = a.%{ 0 } in a.%{ 1 } <- x and exported with val ( .%{ } ): … val ( .%{ } <- ): … Nevertheless, contrarily to Bigarray, there is no implicit conversion for multidimensional array, in other words a .%{0,1} will not work out of the box. However, if needed, it is possible to use qualified indexing operators to circumvent this difficulty: module D1 = struct let ( .%{} ) a k = a.{k} end module D2 = struct let ( .%{} ) a (k,l) = a.{k,l} end let x_ij = mat.D2.%{i, j} let x_0 = vector.D1.%{0} See also the manual for more details: http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#s%3Aindex-operators . − octachron. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Caml-list] Subtyping (or something like it) 2017-11-17 13:01 ` octachron @ 2017-11-17 16:13 ` Reed Wilson 2017-11-17 16:32 ` Leo White 0 siblings, 1 reply; 6+ messages in thread From: Reed Wilson @ 2017-11-17 16:13 UTC (permalink / raw) To: octachron; +Cc: caml-list [-- Attachment #1: Type: text/plain, Size: 2073 bytes --] I hadn't noticed that 4.06 will let me extend indexing. It's certainly a nice feature to have; I'll throw it in :) I actually think I can use that to great effect - a lot of this is used to pack data into structures which are sent to/from C, the network, files, etc.. Having multiple ways of indexing it could be quite helpful for getting/setting multiple different types of data. let ( .!{ } ) = get_1byte_int let ( .@{ } ) = get_2byte_int let ( .${ } ) = get_4byte_int let ( .*{ } ) = get_8byte_int Where the extension character is shift+number of bytes (at least on my keyboard...) I'm a bit worried that it'll start looking like Perl, but time will tell. Thanks for the great ideas! On Fri, Nov 17, 2017 at 5:01 AM, octachron <octa@polychoron.fr> wrote: > With OCaml 4.06, if what you really want is to have a nice syntax for > array indexing, one solution would be to define your own indexing operators: > > let ( .%{ } ) a k = a.{k} > let ( .%{ } <- ) a k x = a.{k} <- x > > These operators can be used like standard indexing operators > > let x = a.%{ 0 } in > a.%{ 1 } <- x > > and exported with > > val ( .%{ } ): … > val ( .%{ } <- ): … > > Nevertheless, contrarily to Bigarray, there is no implicit conversion for > multidimensional array, > in other words > > a .%{0,1} > > will not work out of the box. > > However, if needed, it is possible to use qualified indexing operators to > circumvent this difficulty: > > module D1 = struct let ( .%{} ) a k = a.{k} end > module D2 = struct let ( .%{} ) a (k,l) = a.{k,l} end > let x_ij = mat.D2.%{i, j} > let x_0 = vector.D1.%{0} > > See also the manual for more details: http://caml.inria.fr/pub/docs/ > manual-ocaml/extn.html#s%3Aindex-operators . > > − octachron. > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > -- ç [-- Attachment #2: Type: text/html, Size: 3117 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Caml-list] Subtyping (or something like it) 2017-11-17 16:13 ` Reed Wilson @ 2017-11-17 16:32 ` Leo White 0 siblings, 0 replies; 6+ messages in thread From: Leo White @ 2017-11-17 16:32 UTC (permalink / raw) To: caml-list [-- Attachment #1: Type: text/plain, Size: 621 bytes --] > Where the extension character is shift+number of bytes (at least on my > keyboard...) I'm a bit worried that it'll start> looking like Perl, but time will tell. Personally, I would go with something like: module B1 = struct let ( .%{ } ) = get_1byte_int end module B2 = struct let ( .%{ } ) = get_2byte_int end module B4 = struct let ( .%{ } ) = get_4byte_int end module B8 = struct let ( .%{ } ) = get_8byte_int end Which gives you similar convenience: foo.B1.%{index} foo.B2.%{index} foo.B4.%{index} foo.B8.%{index} without drifting into Perl territory. Regards, Leo [-- Attachment #2: Type: text/html, Size: 1385 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-11-17 16:32 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-11-16 21:46 [Caml-list] Subtyping (or something like it) Reed Wilson 2017-11-17 0:49 ` Yawar Amin 2017-11-17 2:05 ` Reed Wilson 2017-11-17 13:01 ` octachron 2017-11-17 16:13 ` Reed Wilson 2017-11-17 16:32 ` Leo White
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox