<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    There's a proposal at the moment to add support for TDNR to Haskell
    - to leverage "the power of the dot" (e.g. for intellisense).<br>
    <br>
<a class="moz-txt-link-freetext" href="http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution">http://hackage.haskell.org/trac/haskell-prime/wiki/TypeDirectedNameResolution</a><br>
    <br>
    I approve of the goal, but I'd like to suggest a different approach.<br>
    <br>
    My basic idea is stolen from Bertrand Meyer (Object-Oriented
    Software Construction, second edition). Basically, a class *is* both
    a module and a type. Quote...<br>
    <br>
    &nbsp; Classes as modules<br>
    <br>
    &nbsp; Object orientation is primarily an architectural technique: its
    major effect is on the<br>
    &nbsp; modular structure of software systems.<br>
    <br>
    &nbsp; The key role here is again played by classes. A class describes
    not just a type of<br>
    &nbsp; objects but also a modular unit. In a pure object-oriented
    approach:<br>
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Classes should be the only modules.<br>
    <br>
    By the logic of equivalence relations, we can conclude that a type
    *is* a module. Only I'd adapt that a little. In C++, the following
    operators can all be used to access the "module" for some type or
    value...<br>
    <br>
    <ul>
      <li><tt>::&nbsp;&nbsp; Scope resolution</tt></li>
      <li><tt>.&nbsp;&nbsp;&nbsp; Member dereference</tt></li>
      <li><tt>-&gt;&nbsp;&nbsp; Member dereference via a pointer</tt></li>
      <li><tt>.*&nbsp;&nbsp; Member-pointer dereference</tt></li>
      <li><tt>-&gt;*&nbsp; Member-pointer dereference via a pointer</tt></li>
    </ul>
    In C++, a type and an instance each have their own modules. A
    (smart) pointer has its own module, separate from the module for the
    type it points to. And member-pointers exist because sometimes
    there's a need to reference a member without knowing or (yet) caring
    which instance.<br>
    <br>
    We already have member pointers - the functions that map an instance
    to the field value. It would make some sense if these could be
    placed in a module associated with the type (not the instance).<br>
    <br>
    When an instance is created of a type, that can effectively (without
    run-time overhead) create a new module associated with the new
    instance. This will contain the same field-access functions, but
    with the instance parameter already curried in.<br>
    <br>
    So there's no real need for any new meaning of the . operator - it's
    just access to names within a module. And there's no need for a new
    mechanism for accessing fields - only for a way to place them in
    that module scope, and a little sugar that gives us the same
    field-access function but with the instance parameter already
    curried in.<br>
    <br>
    Once we have these modules containing compiler-generated
    field-access functions, though, it makes some sense to allow
    additional functions (and perhaps types) to be added within that
    types module explicitly by the programmer. It may also make sense to
    allow functions to be explicitly defined which will be added to the
    instance-modules and support the prefix-instance-parameter sugar.<br>
    <br>
    Finally, as with C++, when dealing with IORef and similar, it make
    make sense to have a separate -&gt; operator (spelled differently,
    of course). Or it could use the standard dot. C++ and D disagree in
    this (in C++, the smart pointer has its own module separate from the
    pointed-at instance - in D, there is no -&gt; or equivalent).<br>
    <br>
    As an aside, Ada has already gone through a related transition. The
    original Ada 83 had variant records, but no "true classes". In Ada
    95, "tagged types" were added which were like variant records, but
    which supported inheritance and run-time dispatch. The discriminant
    is replaced by a "tag" which is presumably implemented as a virtual
    table pointer. However, functions and procedures weren't members.
    The typical call of a "method" would be...<br>
    <br>
    &nbsp;&nbsp;&nbsp; packagename.procedure_name ( instance_arg, other_args );<br>
    <br>
    Ada 2005 added some workarounds to allow conventional OOP call
    notation. See section 1.3 of the Ada 2005 rationale for details.
    However, it all feels a bit kludgy. In particular, the procedures
    and functions still aren't members - there are just some special
    rules for when they can be used as if they were. I've not actually
    used Ada 2005, but I'd bet some confusion can result from that.<br>
    <br>
    Personally, I think Meyer was at least partly right - if types (and
    instances) are modules, the kludge-factor is much lower. C++
    actually doesn't get this quite right IMO (you can access static
    class members through the instance objects, for example, not just
    through the classes), but C++ classes *do* act mostly like modules
    and that is a very useful trait - particularly within the
    declarative sublanguage (templates etc).<br>
    <br>
  </body>
</html>