caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [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;
as well as URLs for NNTP newsgroup(s).