caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Expressing module sig and impl in mli file
@ 2012-09-18 21:02 Malcolm Matalka
  2012-09-18 21:13 ` Gabriel Scherer
  0 siblings, 1 reply; 12+ messages in thread
From: Malcolm Matalka @ 2012-09-18 21:02 UTC (permalink / raw)
  To: caml-list

I'm sure this question has been asked before but I didn't see it in
the Ocaml FAQ and I'm not sure how to express it for a search.

In short, how do I express the following line in a .mli file:

module Foo : Bar = Baz

What I want to accomplish is make present the module Foo to the user,
where they know both the interface and the concerete types on Foo.

Thanks!

/Malcolm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-18 21:02 [Caml-list] Expressing module sig and impl in mli file Malcolm Matalka
@ 2012-09-18 21:13 ` Gabriel Scherer
  2012-09-18 21:31   ` Malcolm Matalka
  0 siblings, 1 reply; 12+ messages in thread
From: Gabriel Scherer @ 2012-09-18 21:13 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: caml-list

From the outside, there is no point in trying to make a difference
between an "interface" and "concrete types": what users see of the
module is exactly its interface, just as what you see of a value
(through an interface boundary) is its type only. There are exotic
cases where you could want to publish a value definition (or module
implementation) through a component boundary, but that's probably not
your concern here.

So my intuitive answer (but maybe some other posters will differ) is
that, in an interface, only "module Foo : Bar" makes sense. I do not
understand why you would want the implementation to also be available.
You may be facing a problem that is different than the one you think.
Could you provide a concrete example of what you're trying to do?

Making a guess: a mistake people often make when using the OCaml
module system is to seal a module with abstract types when they
actually don't want to hide the types, but only to check that the
signature are compatible. For example, with the signature "module type
Ty = sig type t end", people will try to write "module M : Ty = struct
type t = int end" and then be surprised than "(1 : M.t)" does not
type-check. This is because "module M : Ty = <Foo>" is equivalent to
"module M = (<Foo> : Ty)" which coerces <Foo> into the signature Ty
(where "t" is abstract), and no richer. A workaround is to define
"module M = <Foo>" and then separately "module M_unused = (M : Ty)" if
you want to make sure that the interface is compatible, or to refine
it with "module M : (Ty with type t = int) = <Foo>". Not sure that is
actually your problem, though.

Finally, if you have a module implementation and are not sure what its
precise, most permissive signature is, "ocamlc -i" can help you by
printing the inferred interface.

On Tue, Sep 18, 2012 at 11:02 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
> I'm sure this question has been asked before but I didn't see it in
> the Ocaml FAQ and I'm not sure how to express it for a search.
>
> In short, how do I express the following line in a .mli file:
>
> module Foo : Bar = Baz
>
> What I want to accomplish is make present the module Foo to the user,
> where they know both the interface and the concerete types on Foo.
>
> Thanks!
>
> /Malcolm
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-18 21:13 ` Gabriel Scherer
@ 2012-09-18 21:31   ` Malcolm Matalka
  2012-09-18 22:40     ` Malcolm Matalka
  0 siblings, 1 reply; 12+ messages in thread
From: Malcolm Matalka @ 2012-09-18 21:31 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: caml-list

Thanks for the response.  I think I found another way to express what I'm after:

module Foo : sig include Bar with type t = Baz.t end

For the specific use case I have (trying to create a module that is an
Identifier from Core) this seems to work nicely.

/M

On Tue, Sep 18, 2012 at 11:13 PM, Gabriel Scherer
<gabriel.scherer@gmail.com> wrote:
> From the outside, there is no point in trying to make a difference
> between an "interface" and "concrete types": what users see of the
> module is exactly its interface, just as what you see of a value
> (through an interface boundary) is its type only. There are exotic
> cases where you could want to publish a value definition (or module
> implementation) through a component boundary, but that's probably not
> your concern here.
>
> So my intuitive answer (but maybe some other posters will differ) is
> that, in an interface, only "module Foo : Bar" makes sense. I do not
> understand why you would want the implementation to also be available.
> You may be facing a problem that is different than the one you think.
> Could you provide a concrete example of what you're trying to do?
>
> Making a guess: a mistake people often make when using the OCaml
> module system is to seal a module with abstract types when they
> actually don't want to hide the types, but only to check that the
> signature are compatible. For example, with the signature "module type
> Ty = sig type t end", people will try to write "module M : Ty = struct
> type t = int end" and then be surprised than "(1 : M.t)" does not
> type-check. This is because "module M : Ty = <Foo>" is equivalent to
> "module M = (<Foo> : Ty)" which coerces <Foo> into the signature Ty
> (where "t" is abstract), and no richer. A workaround is to define
> "module M = <Foo>" and then separately "module M_unused = (M : Ty)" if
> you want to make sure that the interface is compatible, or to refine
> it with "module M : (Ty with type t = int) = <Foo>". Not sure that is
> actually your problem, though.
>
> Finally, if you have a module implementation and are not sure what its
> precise, most permissive signature is, "ocamlc -i" can help you by
> printing the inferred interface.
>
> On Tue, Sep 18, 2012 at 11:02 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
>> I'm sure this question has been asked before but I didn't see it in
>> the Ocaml FAQ and I'm not sure how to express it for a search.
>>
>> In short, how do I express the following line in a .mli file:
>>
>> module Foo : Bar = Baz
>>
>> What I want to accomplish is make present the module Foo to the user,
>> where they know both the interface and the concerete types on Foo.
>>
>> Thanks!
>>
>> /Malcolm
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa-roc.inria.fr/wws/info/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-18 21:31   ` Malcolm Matalka
@ 2012-09-18 22:40     ` Malcolm Matalka
  2012-09-19  2:11       ` Edgar Friendly
  2012-09-19  7:25       ` Jacques Garrigue
  0 siblings, 2 replies; 12+ messages in thread
From: Malcolm Matalka @ 2012-09-18 22:40 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: caml-list

I spoke too soon!  Below is my testcase and error.  Where did I go wrong?

foo.mli:
open Core.Std

module Bar : sig
  include Identifier with type t = String.t
end

foo.ml:
open Core.Std

module Bar : Identifier = String

The error:
       Type declarations do not match:
         type t = Bar.t
       is not included in
         type t = Core.Std.String.t

/M

On Tue, Sep 18, 2012 at 11:31 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
> Thanks for the response.  I think I found another way to express what I'm after:
>
> module Foo : sig include Bar with type t = Baz.t end
>
> For the specific use case I have (trying to create a module that is an
> Identifier from Core) this seems to work nicely.
>
> /M
>
> On Tue, Sep 18, 2012 at 11:13 PM, Gabriel Scherer
> <gabriel.scherer@gmail.com> wrote:
>> From the outside, there is no point in trying to make a difference
>> between an "interface" and "concrete types": what users see of the
>> module is exactly its interface, just as what you see of a value
>> (through an interface boundary) is its type only. There are exotic
>> cases where you could want to publish a value definition (or module
>> implementation) through a component boundary, but that's probably not
>> your concern here.
>>
>> So my intuitive answer (but maybe some other posters will differ) is
>> that, in an interface, only "module Foo : Bar" makes sense. I do not
>> understand why you would want the implementation to also be available.
>> You may be facing a problem that is different than the one you think.
>> Could you provide a concrete example of what you're trying to do?
>>
>> Making a guess: a mistake people often make when using the OCaml
>> module system is to seal a module with abstract types when they
>> actually don't want to hide the types, but only to check that the
>> signature are compatible. For example, with the signature "module type
>> Ty = sig type t end", people will try to write "module M : Ty = struct
>> type t = int end" and then be surprised than "(1 : M.t)" does not
>> type-check. This is because "module M : Ty = <Foo>" is equivalent to
>> "module M = (<Foo> : Ty)" which coerces <Foo> into the signature Ty
>> (where "t" is abstract), and no richer. A workaround is to define
>> "module M = <Foo>" and then separately "module M_unused = (M : Ty)" if
>> you want to make sure that the interface is compatible, or to refine
>> it with "module M : (Ty with type t = int) = <Foo>". Not sure that is
>> actually your problem, though.
>>
>> Finally, if you have a module implementation and are not sure what its
>> precise, most permissive signature is, "ocamlc -i" can help you by
>> printing the inferred interface.
>>
>> On Tue, Sep 18, 2012 at 11:02 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
>>> I'm sure this question has been asked before but I didn't see it in
>>> the Ocaml FAQ and I'm not sure how to express it for a search.
>>>
>>> In short, how do I express the following line in a .mli file:
>>>
>>> module Foo : Bar = Baz
>>>
>>> What I want to accomplish is make present the module Foo to the user,
>>> where they know both the interface and the concerete types on Foo.
>>>
>>> Thanks!
>>>
>>> /Malcolm
>>>
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa-roc.inria.fr/wws/info/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-18 22:40     ` Malcolm Matalka
@ 2012-09-19  2:11       ` Edgar Friendly
  2012-09-19  7:11         ` David House
  2012-09-19  7:25       ` Jacques Garrigue
  1 sibling, 1 reply; 12+ messages in thread
From: Edgar Friendly @ 2012-09-19  2:11 UTC (permalink / raw)
  To: caml-list

> module Bar : Identifier = String
The problem is here; the ": Identifier" removes any details of Bar 
except what's in Identifier.  Just remove this type restriction and 
everything should typecheck.

E.

On 9/18/2012 6:40 PM, Malcolm Matalka wrote:
> I spoke too soon!  Below is my testcase and error.  Where did I go wrong?
>
> foo.mli:
> open Core.Std
>
> module Bar : sig
>    include Identifier with type t = String.t
> end
>
> foo.ml:
> open Core.Std
>
> module Bar : Identifier = String
>
> The error:
>         Type declarations do not match:
>           type t = Bar.t
>         is not included in
>           type t = Core.Std.String.t
>
> /M
>
> On Tue, Sep 18, 2012 at 11:31 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
>> Thanks for the response.  I think I found another way to express what I'm after:
>>
>> module Foo : sig include Bar with type t = Baz.t end
>>
>> For the specific use case I have (trying to create a module that is an
>> Identifier from Core) this seems to work nicely.
>>
>> /M
>>
>> On Tue, Sep 18, 2012 at 11:13 PM, Gabriel Scherer
>> <gabriel.scherer@gmail.com> wrote:
>>>  From the outside, there is no point in trying to make a difference
>>> between an "interface" and "concrete types": what users see of the
>>> module is exactly its interface, just as what you see of a value
>>> (through an interface boundary) is its type only. There are exotic
>>> cases where you could want to publish a value definition (or module
>>> implementation) through a component boundary, but that's probably not
>>> your concern here.
>>>
>>> So my intuitive answer (but maybe some other posters will differ) is
>>> that, in an interface, only "module Foo : Bar" makes sense. I do not
>>> understand why you would want the implementation to also be available.
>>> You may be facing a problem that is different than the one you think.
>>> Could you provide a concrete example of what you're trying to do?
>>>
>>> Making a guess: a mistake people often make when using the OCaml
>>> module system is to seal a module with abstract types when they
>>> actually don't want to hide the types, but only to check that the
>>> signature are compatible. For example, with the signature "module type
>>> Ty = sig type t end", people will try to write "module M : Ty = struct
>>> type t = int end" and then be surprised than "(1 : M.t)" does not
>>> type-check. This is because "module M : Ty = <Foo>" is equivalent to
>>> "module M = (<Foo> : Ty)" which coerces <Foo> into the signature Ty
>>> (where "t" is abstract), and no richer. A workaround is to define
>>> "module M = <Foo>" and then separately "module M_unused = (M : Ty)" if
>>> you want to make sure that the interface is compatible, or to refine
>>> it with "module M : (Ty with type t = int) = <Foo>". Not sure that is
>>> actually your problem, though.
>>>
>>> Finally, if you have a module implementation and are not sure what its
>>> precise, most permissive signature is, "ocamlc -i" can help you by
>>> printing the inferred interface.
>>>
>>> On Tue, Sep 18, 2012 at 11:02 PM, Malcolm Matalka <mmatalka@gmail.com> wrote:
>>>> I'm sure this question has been asked before but I didn't see it in
>>>> the Ocaml FAQ and I'm not sure how to express it for a search.
>>>>
>>>> In short, how do I express the following line in a .mli file:
>>>>
>>>> module Foo : Bar = Baz
>>>>
>>>> What I want to accomplish is make present the module Foo to the user,
>>>> where they know both the interface and the concerete types on Foo.
>>>>
>>>> Thanks!
>>>>
>>>> /Malcolm
>>>>
>>>> --
>>>> Caml-list mailing list.  Subscription management and archives:
>>>> https://sympa-roc.inria.fr/wws/info/caml-list
>>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  2:11       ` Edgar Friendly
@ 2012-09-19  7:11         ` David House
  2012-09-19  7:36           ` Malcolm Matalka
  0 siblings, 1 reply; 12+ messages in thread
From: David House @ 2012-09-19  7:11 UTC (permalink / raw)
  To: Edgar Friendly; +Cc: caml-list

The standard way of doing this is as follows (note that Identifier is
changing to Identifiable in the next version, so I'll use that
terminology):

module Bar : sig
  type t = string
  include Identifiable with type t := t
end

But if this is literally what you're doing, I'm sort of confused. The
point of identifiable is that you have explicit to_string/from_string
functions and the type equality with string is not exposed. E.g. you
might want to use a different comparison function than string
equality. If you expose the type equality with string, then people are
free to use String.compare on your type, so you don't get the
abstraction you wanted.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-18 22:40     ` Malcolm Matalka
  2012-09-19  2:11       ` Edgar Friendly
@ 2012-09-19  7:25       ` Jacques Garrigue
  1 sibling, 0 replies; 12+ messages in thread
From: Jacques Garrigue @ 2012-09-19  7:25 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: caml-list

On Wed, Sep 19, 2012 at 7:40 AM, Malcolm Matalka <mmatalka@gmail.com> wrote:
> I spoke too soon!  Below is my testcase and error.  Where did I go wrong?
>
> foo.mli:
> open Core.Std
>
> module Bar : sig
>   include Identifier with type t = String.t
> end
>
> foo.ml:
> open Core.Std
>
> module Bar : Identifier = String
>
> The error:
>        Type declarations do not match:
>          type t = Bar.t
>        is not included in
>          type t = Core.Std.String.t

First comment: there is no need to use include here.
You can just write

  module Bar : Identifier with type t = String.t

in the interface.
Since there is an interface, there is not need to restrict Bar
in the implementation, so just write:

  module Bar = String

If you want to add a signature in the implementation,
it should be a subtype of the interface signature.

Jacques Garrigue

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  7:11         ` David House
@ 2012-09-19  7:36           ` Malcolm Matalka
  2012-09-19  7:49             ` David House
  0 siblings, 1 reply; 12+ messages in thread
From: Malcolm Matalka @ 2012-09-19  7:36 UTC (permalink / raw)
  To: David House; +Cc: Edgar Friendly, caml-list

Yes I think I'm confused.  In all parts of this module I want the
Identifiable behaviour, but at the same time I want a Map of these
identifiers to something, so this turned in to me trying to jerry-rig
that rather than thinking about what I actually want.

Can something that is Identifiable be the key to a Map (in Core)?  Am
I doing something wrong if I want that?

Thanks

/M

On Wed, Sep 19, 2012 at 9:11 AM, David House <dmhouse@gmail.com> wrote:
> The standard way of doing this is as follows (note that Identifier is
> changing to Identifiable in the next version, so I'll use that
> terminology):
>
> module Bar : sig
>   type t = string
>   include Identifiable with type t := t
> end
>
> But if this is literally what you're doing, I'm sort of confused. The
> point of identifiable is that you have explicit to_string/from_string
> functions and the type equality with string is not exposed. E.g. you
> might want to use a different comparison function than string
> equality. If you expose the type equality with string, then people are
> free to use String.compare on your type, so you don't get the
> abstraction you wanted.
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  7:36           ` Malcolm Matalka
@ 2012-09-19  7:49             ` David House
  2012-09-19  7:51               ` David House
  0 siblings, 1 reply; 12+ messages in thread
From: David House @ 2012-09-19  7:49 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: Edgar Friendly, caml-list

So, this depends. If you have an identifier type that are internally
just strings, then the simplest way is as I said before:

module Bar = String_id (* or = String, both will work *)

module Bar : sig
  type t
  include Identifiable with type t := t
  (* other operations on your Bar go here *)
end

The Identifiable signature includes the Comparable signature, which
includes a map module. So then you have a type ['a Bar.Map.t], which
is a map from Bar.t's to 'a.

If you want to use your own comparison function, then you can do the following:

module Bar = struct
  module T = struct
    type t = string with sexp
    let compare = ...
  end
  include T
  include Comparable.Make(T)
  let of_string = Fn.id
  let to_string = Fn.id
end

module Bar : sig
  type t
  include Comparable with type t := t (* Map module, compare, etc. *)
  include Strinagable with type t := t (* to_string, of_string *)
end

This will generate a map module that uses the comparison function you define.

If additionally you can define a hash function, then you can do the following:

module Bar = struct
  module T = struct
    type t = string with sexp
    let compare t1 t2 = ...
    let hash t = ...
  end
  include T
  include Comparable.Make(T)
  include Hashable.Make(T)
  let of_string = Fn.id
  let to_string = Fn.id
end

module Bar : sig
  type t
  include Comparable with type t := t (* Set module, Map module,
compare, etc. *)
  include Strinagable with type t := t (* to_string, of_string *)
  include Hashable with type t := t (* hash, Table module, Hash_set
module, etc. *)
end

And the final signature is actually equal (very nearly) to
Identifiable, so you'd just write:

module Bar : Identifiable

On 19 September 2012 08:36, Malcolm Matalka <mmatalka@gmail.com> wrote:
> Yes I think I'm confused.  In all parts of this module I want the
> Identifiable behaviour, but at the same time I want a Map of these
> identifiers to something, so this turned in to me trying to jerry-rig
> that rather than thinking about what I actually want.
>
> Can something that is Identifiable be the key to a Map (in Core)?  Am
> I doing something wrong if I want that?
>
> Thanks
>
> /M
>
> On Wed, Sep 19, 2012 at 9:11 AM, David House <dmhouse@gmail.com> wrote:
>> The standard way of doing this is as follows (note that Identifier is
>> changing to Identifiable in the next version, so I'll use that
>> terminology):
>>
>> module Bar : sig
>>   type t = string
>>   include Identifiable with type t := t
>> end
>>
>> But if this is literally what you're doing, I'm sort of confused. The
>> point of identifiable is that you have explicit to_string/from_string
>> functions and the type equality with string is not exposed. E.g. you
>> might want to use a different comparison function than string
>> equality. If you expose the type equality with string, then people are
>> free to use String.compare on your type, so you don't get the
>> abstraction you wanted.
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa-roc.inria.fr/wws/info/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  7:49             ` David House
@ 2012-09-19  7:51               ` David House
  2012-09-19  8:00                 ` Malcolm Matalka
  0 siblings, 1 reply; 12+ messages in thread
From: David House @ 2012-09-19  7:51 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: Edgar Friendly, caml-list

Oh, and one more thing to mention. If your identifier types are not
strings, but you have of_string and to_string functions, then you can
do the following:

module Bar = struct
  module T = struct
    type t = ...
    let of_string = ...
    let to_string = ...
  end
  include Identifiable.Of_stringable(T)
end

module Bar : Identifiable

On 19 September 2012 08:49, David House <dmhouse@gmail.com> wrote:
> So, this depends. If you have an identifier type that are internally
> just strings, then the simplest way is as I said before:
>
> module Bar = String_id (* or = String, both will work *)
>
> module Bar : sig
>   type t
>   include Identifiable with type t := t
>   (* other operations on your Bar go here *)
> end
>
> The Identifiable signature includes the Comparable signature, which
> includes a map module. So then you have a type ['a Bar.Map.t], which
> is a map from Bar.t's to 'a.
>
> If you want to use your own comparison function, then you can do the following:
>
> module Bar = struct
>   module T = struct
>     type t = string with sexp
>     let compare = ...
>   end
>   include T
>   include Comparable.Make(T)
>   let of_string = Fn.id
>   let to_string = Fn.id
> end
>
> module Bar : sig
>   type t
>   include Comparable with type t := t (* Map module, compare, etc. *)
>   include Strinagable with type t := t (* to_string, of_string *)
> end
>
> This will generate a map module that uses the comparison function you define.
>
> If additionally you can define a hash function, then you can do the following:
>
> module Bar = struct
>   module T = struct
>     type t = string with sexp
>     let compare t1 t2 = ...
>     let hash t = ...
>   end
>   include T
>   include Comparable.Make(T)
>   include Hashable.Make(T)
>   let of_string = Fn.id
>   let to_string = Fn.id
> end
>
> module Bar : sig
>   type t
>   include Comparable with type t := t (* Set module, Map module,
> compare, etc. *)
>   include Strinagable with type t := t (* to_string, of_string *)
>   include Hashable with type t := t (* hash, Table module, Hash_set
> module, etc. *)
> end
>
> And the final signature is actually equal (very nearly) to
> Identifiable, so you'd just write:
>
> module Bar : Identifiable
>
> On 19 September 2012 08:36, Malcolm Matalka <mmatalka@gmail.com> wrote:
>> Yes I think I'm confused.  In all parts of this module I want the
>> Identifiable behaviour, but at the same time I want a Map of these
>> identifiers to something, so this turned in to me trying to jerry-rig
>> that rather than thinking about what I actually want.
>>
>> Can something that is Identifiable be the key to a Map (in Core)?  Am
>> I doing something wrong if I want that?
>>
>> Thanks
>>
>> /M
>>
>> On Wed, Sep 19, 2012 at 9:11 AM, David House <dmhouse@gmail.com> wrote:
>>> The standard way of doing this is as follows (note that Identifier is
>>> changing to Identifiable in the next version, so I'll use that
>>> terminology):
>>>
>>> module Bar : sig
>>>   type t = string
>>>   include Identifiable with type t := t
>>> end
>>>
>>> But if this is literally what you're doing, I'm sort of confused. The
>>> point of identifiable is that you have explicit to_string/from_string
>>> functions and the type equality with string is not exposed. E.g. you
>>> might want to use a different comparison function than string
>>> equality. If you expose the type equality with string, then people are
>>> free to use String.compare on your type, so you don't get the
>>> abstraction you wanted.
>>>
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa-roc.inria.fr/wws/info/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  7:51               ` David House
@ 2012-09-19  8:00                 ` Malcolm Matalka
  2012-09-19  8:11                   ` Gabriel Scherer
  0 siblings, 1 reply; 12+ messages in thread
From: Malcolm Matalka @ 2012-09-19  8:00 UTC (permalink / raw)
  To: David House; +Cc: Edgar Friendly, caml-list

Ah great!  What you said works!  The problem I was running into was
trying to do Map.Make(Bar).  Still getting used to how Core organizes
things.

I looked around a bit on google as well but couldn't find an answer to
this: what is the difference between = and := in a 'with'?  The
language reference section I looked at didn't seem to make a
distinction.

Thanks again,
/M

On Wed, Sep 19, 2012 at 9:51 AM, David House <dmhouse@gmail.com> wrote:
> Oh, and one more thing to mention. If your identifier types are not
> strings, but you have of_string and to_string functions, then you can
> do the following:
>
> module Bar = struct
>   module T = struct
>     type t = ...
>     let of_string = ...
>     let to_string = ...
>   end
>   include Identifiable.Of_stringable(T)
> end
>
> module Bar : Identifiable
>
> On 19 September 2012 08:49, David House <dmhouse@gmail.com> wrote:
>> So, this depends. If you have an identifier type that are internally
>> just strings, then the simplest way is as I said before:
>>
>> module Bar = String_id (* or = String, both will work *)
>>
>> module Bar : sig
>>   type t
>>   include Identifiable with type t := t
>>   (* other operations on your Bar go here *)
>> end
>>
>> The Identifiable signature includes the Comparable signature, which
>> includes a map module. So then you have a type ['a Bar.Map.t], which
>> is a map from Bar.t's to 'a.
>>
>> If you want to use your own comparison function, then you can do the following:
>>
>> module Bar = struct
>>   module T = struct
>>     type t = string with sexp
>>     let compare = ...
>>   end
>>   include T
>>   include Comparable.Make(T)
>>   let of_string = Fn.id
>>   let to_string = Fn.id
>> end
>>
>> module Bar : sig
>>   type t
>>   include Comparable with type t := t (* Map module, compare, etc. *)
>>   include Strinagable with type t := t (* to_string, of_string *)
>> end
>>
>> This will generate a map module that uses the comparison function you define.
>>
>> If additionally you can define a hash function, then you can do the following:
>>
>> module Bar = struct
>>   module T = struct
>>     type t = string with sexp
>>     let compare t1 t2 = ...
>>     let hash t = ...
>>   end
>>   include T
>>   include Comparable.Make(T)
>>   include Hashable.Make(T)
>>   let of_string = Fn.id
>>   let to_string = Fn.id
>> end
>>
>> module Bar : sig
>>   type t
>>   include Comparable with type t := t (* Set module, Map module,
>> compare, etc. *)
>>   include Strinagable with type t := t (* to_string, of_string *)
>>   include Hashable with type t := t (* hash, Table module, Hash_set
>> module, etc. *)
>> end
>>
>> And the final signature is actually equal (very nearly) to
>> Identifiable, so you'd just write:
>>
>> module Bar : Identifiable
>>
>> On 19 September 2012 08:36, Malcolm Matalka <mmatalka@gmail.com> wrote:
>>> Yes I think I'm confused.  In all parts of this module I want the
>>> Identifiable behaviour, but at the same time I want a Map of these
>>> identifiers to something, so this turned in to me trying to jerry-rig
>>> that rather than thinking about what I actually want.
>>>
>>> Can something that is Identifiable be the key to a Map (in Core)?  Am
>>> I doing something wrong if I want that?
>>>
>>> Thanks
>>>
>>> /M
>>>
>>> On Wed, Sep 19, 2012 at 9:11 AM, David House <dmhouse@gmail.com> wrote:
>>>> The standard way of doing this is as follows (note that Identifier is
>>>> changing to Identifiable in the next version, so I'll use that
>>>> terminology):
>>>>
>>>> module Bar : sig
>>>>   type t = string
>>>>   include Identifiable with type t := t
>>>> end
>>>>
>>>> But if this is literally what you're doing, I'm sort of confused. The
>>>> point of identifiable is that you have explicit to_string/from_string
>>>> functions and the type equality with string is not exposed. E.g. you
>>>> might want to use a different comparison function than string
>>>> equality. If you expose the type equality with string, then people are
>>>> free to use String.compare on your type, so you don't get the
>>>> abstraction you wanted.
>>>>
>>>> --
>>>> Caml-list mailing list.  Subscription management and archives:
>>>> https://sympa-roc.inria.fr/wws/info/caml-list
>>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Caml-list] Expressing module sig and impl in mli file
  2012-09-19  8:00                 ` Malcolm Matalka
@ 2012-09-19  8:11                   ` Gabriel Scherer
  0 siblings, 0 replies; 12+ messages in thread
From: Gabriel Scherer @ 2012-09-19  8:11 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: David House, Edgar Friendly, caml-list

The documentation for "destructive substitution" (with t := ...) is
present in the "Language Extensions" section:
  http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc83

On Wed, Sep 19, 2012 at 10:00 AM, Malcolm Matalka <mmatalka@gmail.com> wrote:
> Ah great!  What you said works!  The problem I was running into was
> trying to do Map.Make(Bar).  Still getting used to how Core organizes
> things.
>
> I looked around a bit on google as well but couldn't find an answer to
> this: what is the difference between = and := in a 'with'?  The
> language reference section I looked at didn't seem to make a
> distinction.
>
> Thanks again,
> /M
>
> On Wed, Sep 19, 2012 at 9:51 AM, David House <dmhouse@gmail.com> wrote:
>> Oh, and one more thing to mention. If your identifier types are not
>> strings, but you have of_string and to_string functions, then you can
>> do the following:
>>
>> module Bar = struct
>>   module T = struct
>>     type t = ...
>>     let of_string = ...
>>     let to_string = ...
>>   end
>>   include Identifiable.Of_stringable(T)
>> end
>>
>> module Bar : Identifiable
>>
>> On 19 September 2012 08:49, David House <dmhouse@gmail.com> wrote:
>>> So, this depends. If you have an identifier type that are internally
>>> just strings, then the simplest way is as I said before:
>>>
>>> module Bar = String_id (* or = String, both will work *)
>>>
>>> module Bar : sig
>>>   type t
>>>   include Identifiable with type t := t
>>>   (* other operations on your Bar go here *)
>>> end
>>>
>>> The Identifiable signature includes the Comparable signature, which
>>> includes a map module. So then you have a type ['a Bar.Map.t], which
>>> is a map from Bar.t's to 'a.
>>>
>>> If you want to use your own comparison function, then you can do the following:
>>>
>>> module Bar = struct
>>>   module T = struct
>>>     type t = string with sexp
>>>     let compare = ...
>>>   end
>>>   include T
>>>   include Comparable.Make(T)
>>>   let of_string = Fn.id
>>>   let to_string = Fn.id
>>> end
>>>
>>> module Bar : sig
>>>   type t
>>>   include Comparable with type t := t (* Map module, compare, etc. *)
>>>   include Strinagable with type t := t (* to_string, of_string *)
>>> end
>>>
>>> This will generate a map module that uses the comparison function you define.
>>>
>>> If additionally you can define a hash function, then you can do the following:
>>>
>>> module Bar = struct
>>>   module T = struct
>>>     type t = string with sexp
>>>     let compare t1 t2 = ...
>>>     let hash t = ...
>>>   end
>>>   include T
>>>   include Comparable.Make(T)
>>>   include Hashable.Make(T)
>>>   let of_string = Fn.id
>>>   let to_string = Fn.id
>>> end
>>>
>>> module Bar : sig
>>>   type t
>>>   include Comparable with type t := t (* Set module, Map module,
>>> compare, etc. *)
>>>   include Strinagable with type t := t (* to_string, of_string *)
>>>   include Hashable with type t := t (* hash, Table module, Hash_set
>>> module, etc. *)
>>> end
>>>
>>> And the final signature is actually equal (very nearly) to
>>> Identifiable, so you'd just write:
>>>
>>> module Bar : Identifiable
>>>
>>> On 19 September 2012 08:36, Malcolm Matalka <mmatalka@gmail.com> wrote:
>>>> Yes I think I'm confused.  In all parts of this module I want the
>>>> Identifiable behaviour, but at the same time I want a Map of these
>>>> identifiers to something, so this turned in to me trying to jerry-rig
>>>> that rather than thinking about what I actually want.
>>>>
>>>> Can something that is Identifiable be the key to a Map (in Core)?  Am
>>>> I doing something wrong if I want that?
>>>>
>>>> Thanks
>>>>
>>>> /M
>>>>
>>>> On Wed, Sep 19, 2012 at 9:11 AM, David House <dmhouse@gmail.com> wrote:
>>>>> The standard way of doing this is as follows (note that Identifier is
>>>>> changing to Identifiable in the next version, so I'll use that
>>>>> terminology):
>>>>>
>>>>> module Bar : sig
>>>>>   type t = string
>>>>>   include Identifiable with type t := t
>>>>> end
>>>>>
>>>>> But if this is literally what you're doing, I'm sort of confused. The
>>>>> point of identifiable is that you have explicit to_string/from_string
>>>>> functions and the type equality with string is not exposed. E.g. you
>>>>> might want to use a different comparison function than string
>>>>> equality. If you expose the type equality with string, then people are
>>>>> free to use String.compare on your type, so you don't get the
>>>>> abstraction you wanted.
>>>>>
>>>>> --
>>>>> Caml-list mailing list.  Subscription management and archives:
>>>>> https://sympa-roc.inria.fr/wws/info/caml-list
>>>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>>>>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-09-19  8:11 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-18 21:02 [Caml-list] Expressing module sig and impl in mli file Malcolm Matalka
2012-09-18 21:13 ` Gabriel Scherer
2012-09-18 21:31   ` Malcolm Matalka
2012-09-18 22:40     ` Malcolm Matalka
2012-09-19  2:11       ` Edgar Friendly
2012-09-19  7:11         ` David House
2012-09-19  7:36           ` Malcolm Matalka
2012-09-19  7:49             ` David House
2012-09-19  7:51               ` David House
2012-09-19  8:00                 ` Malcolm Matalka
2012-09-19  8:11                   ` Gabriel Scherer
2012-09-19  7:25       ` Jacques Garrigue

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).