[Grace-core] More thoughts on modules

James Noble kjx at ecs.vuw.ac.nz
Thu Jun 9 03:29:28 PDT 2011


Hi Kim & all 

> More on modules, responding to Andrew's suggestion about using parameters to import modules:
> 
> Allowing for changes in names when importing can be tricky.  The idea in my module system is that one would import the interface (or definition) modules, which make no claim on implementation.  The advantage of this is that the interface modules provide all the information one needs to type-check the new code in the presence of the imported code.  If one were to write modules as taking other modules (or even pieces of other modules) as parameters, you would have to provide all of the kinds of information that is in the definition modules already, making it pretty clunky.  Personally I’d rather import from interface modules and then allow renaming when writing an implementation module for a given interface module.

right - so a key benefit of modules is *separate* / *independent* type checking
(modulo Gilad's comments on non-modularitly of types)

[Hmm. could classes be used as types only within their own module?] 

> Let’s take a very simple example (using interface as the keyword):
> 
> Interface Module DMod {
> 
>    type T {...}  // alternatively can also hide some methods, giving a partial revelation:
>                         // (I used different names, T and U, to make it clearer this time)

this really is Modula-3 style isn't it.

>     type U extends {
>           m:....
>           ...   // list only features you want publicly available outside of module
>     }
> 
>    const o: U    // list type, but not implementation
> 
>    const makeT: S -> T  // closure, not a method, as it’s not sitting in an object.

so do we have closures sitting at the top level?
I guess we must, whatever the syntax is - I quite like S->T, not
sure it's the best, see another reply of mine.
> 
> (As Andrew points out, rather than exporting makeT as a closure, we could instead wrap it in an object and export it.  I have a marginal preference for exporting closures, but either works.  I originally had a variable also being exported, but instead we could export an object like o with getter and setter methods for the variable.)

I guess the issue (again) is: what are we doing?  
How important is this?  I thought we'd agree to go with 
the class-as-factory-object model, classes define "new",
any alternative constructors in factory etc - that andrew talked
about at PLDG, and that I did brief overview of at MSR.
(MethodsOfGrace in svn, should be updated soon)

I understood Kim would still like additional inline factory methods / constructors
in the body of a "class" construct that would call the primary factory "new"
I understand Andrew would still like a very general "extends" operator on
arbitrary objects: I'm happy with a very confined extends syntax which
can only extend a particular *class* and only by calling new.
(i,e. all extends must be extends C.new(...) )
That's what 0.1 spec says, which is where I thought we had agreed.

Kim, do you think we need to reopen that generally,
or are you proposing a different model for creation
in modules than in classes? 

> Implementation Module implements DMod {
> 
>     import EMod  // options would exist to import either all or some of it,
>                             // could also specify whether need to use qualified names or not

OK sure... 

> 
>    type T = EMod.OT
> 
>    type U = EMod.OU
> 
>    const o = EMod.oo
> 
>> }
> 
> This implementation module simply does renaming to make the imported module match up with the names in the definition module.  Now we can link this in as the implementation module corresponding to DMod.

I take it  these "renamings" aren't real renamings, they're declaring defintions
initialised from other places. That "const" for isn't a special "renaming const" - is it?
so the types just establish type aliases:   they look like renamings because the
RHS types EMod.OT etc don't get exported.

racket (& Typed racket) allow renamings I think)

renaming methods on objects of course will be much, much tricker.

> This seems to work pretty simply if we have structural types, as T is now just another name for EMod.OT, so all type specifications in EMod could have their OT’s replaced by T’s without difficulty.

OK right yep.  I think this can still work with (reified) nominal types: T is just another name for the
(underlying) type (meta)object :-)

>  If we had nominal types then we’d have a way to define types so that we ended up with the new name being an alias for the old rather than giving a “new” type (and hence different type), which would not be freely substitutable for the old.

right so in nominal-land, we'd need to be explicit about when "type" created 
new types and when it just set up aliases for old types.

> Now when we import DMod, we would end up getting those items from the EMod implementation, with their names changed.
> 
> If someone would like to work instead with parameters to modules, I’d be interested in seeing how one would write an example like this so that there is enough information that we could do static type-checking of the importing module (before we fill in the formal parameters with the actual parameters).

fair enough!   I think that is a good question 
(hopefully andrew will answer it)   
What type is newspeak's "platform"?
if it's structural, won't it also be horrendous? 

> Please note that all of the above on modules is written from the perspective of statically typed languages.

OK right.   

>  A quick read of Andrew’s paper seems to indicate that similar effects could be obtained by having objects provide (at least) two different encapsulation properties.  One inside the implementation module that would provide calling privileges to all methods of the object.  A different one would be provided for each interface, specifying that only the methods listed in the interface module would be callable from objects that don’t live (or are generated) in the implementation module.  Andrew, does this make sense?

I'm concerned that if we go too far down that way we complicate our (conceptually) simple method dispatch rule.

I do think lurking somewhere under here are questions eg. about the security model 
encapsualtion, etc, that we have yet to resolve.

Mark Miller's E object-capability model is one possibility that just uses objects - but that ends up in a rather different place than partial relevation.

James


More information about the Grace-core mailing list