* [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-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
* 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
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