[Haskell-cafe] Type Directed Name Resolution
illissius at gmail.com
Thu Nov 11 04:51:53 EST 2010
2010/11/11 Gábor Lehel <illissius at gmail.com>:
> I agree with the people who want to decouple the dot-syntax from TDNR
> itself. To quote myself from the publicly-editable wiki page:
> "This might be a really dumb question, but is there any reason TDNR
> needs to be tied to a new syntax for function application? It seems
> strange to me to have one syntax for left-to-right function
> application without TDNR, and then another for right-to-left
> application with it. I would much rather gain TDNR for the existing
> syntax, and then maybe introduce the dot operator as a separate option
> if people want it, which I don't. The reason I don't is that (.) as
> composition and ($) already work in one direction, which is the same
> direction (`foo . bar . baz $ bla` and `foo $ bar $ baz $ bla` are
> interchangeable), and while in a vacuum I might even prefer the
> opposite direction which (.)-as-application uses, it is much more
> important to be consistent. We have a vast body of functions already
> written and designed to be convenient with the existing direction:
> functions are generally of the form `f :: (what to do) -> (what to do
> it with) -> (result)`, which lends itself well to partial
> application/currying and chaining in the existing direction, but not
> the other one. (Object oriented languages which use the dot operator
> indeed also use the reverse order for their methods, with the object
> first and the action second.) Also, reading expressions where
> different parts work in different directions is very confusing. The
> one major exception which works in the other direction is monadic
> bind, (>>=), which I think was a (minor) mistake, and indeed I
> frequently end up using (=<<) instead. Anyway, executive summary: TDNR
> yea, dot operator nay."
> Some further thoughts.
> I would have TDNR apply only in cases where:
> - The functions are all imported from different modules (so you can't
> define overlapping names within the same module);
> - All of the functions have an explicit type signature;
> - The ambiguity can be resolved by looking at the type of the first
> (taking currying into account, only) parameter of each function and,
> looking at the type constructors from the outside in, comparing only
> type constructors which are concrete types, rather than type variables
> (with or without constraints). E.g.:
> -- f :: Int -> [...] and f :: Char -> [...] could be resolved;
> -- f :: Foo Int -> [...] and f :: Foo Char -> [...] could be resolved;
> -- f :: Foo a -> [...] and f :: Bar b -> [...] could be resolved;
> -- f :: Num a => a -> [...] and f :: IsString b => b -> [...] could
> *not* be resolved (even if it is known that the argument type doesn't
> satisfy both constraints);
> -- f :: a Int -> [...] and f :: b Char -> [...] could *not* be
> resolved (though I'm less sure about this one).
> -- Going by the above, neither Foo nor Bar can be type functions.
> -- With more than two functions, each possible pair has to meet the conditions.
I forgot to mention: some kind of similar criteria should probably
apply to the function where 'f' is used (again going by the above
examples) and/or its argument as well. E.g. it should not be possible
to define "g a = f a" and have f be resolved by TDNR when g is used
(even if all of the in-scope functions with the name 'f' meet the
previous criteria), because TDNR is not duck typing.
> I don't have any well-articulated arguments to support this idea, yet;
> it mainly just "feels right". My intuition for TDNR is that it has no
> connection to semantics, and it is not intended as a means of defining
> an interface: it is merely a syntactic convenience. If you want to
> define an interface, use a type class. TDNR would be a convenience for
> the case where you have imported multiple modules using a function of
> the same name with obviously different types (whether the functions do
> similar or different things is beside the point). Comparing to C++
> (though it's unlikely to help my case to mention that language here,
> but whatever), I feel that type classes : TDNR :: virtual functions :
> static overloading.
> And, in any case, as a language extension nobody would be forced to
> use it if they don't like it. (I personally would find it very
> useful). I think the fact that language extensions need to meet (much)
> lesser criteria than changes to the language standard itself is
> plainly evidenced by the existence of IncoherentInstances, which
> nobody in their right mind would ever consider standardizing (or, for
> that matter, ever enabling).
> On Wed, Nov 10, 2010 at 10:59 AM, John Smith <voldermort at hotmail.com> wrote:
>> Type-directed name resolution, as originally proposed for Haskell', has now
>> been proposed for GHC. Obvious benefits of this are that conflicting
>> function names from imported modules can be used without qualification
>> (verbose) or pseudo-Hungarian renaming (verbose, and requires that you
>> control the source, and perform the same renaming in all dependencies). This
>> is important for both readability and programming in the large, particularly
>> where records are concerned, as the duplicate name problem cannot be
>> alleviated with typeclasses, and it is often desirable to have the same
>> field names for many records in the same module.
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
> Work is punishment for failing to procrastinate effectively.
Work is punishment for failing to procrastinate effectively.
More information about the Haskell-Cafe