[Haskell-cafe] Some thoughts on Type-Directed Name Resolution
AntC
anthony_clayden at clear.net.nz
Fri Feb 3 14:37:49 CET 2012
Gábor Lehel <illissius <at> gmail.com> writes:
>
> On Fri, Feb 3, 2012 at 10:30 AM, AntC <anthony_clayden <at> clear.net.nz>
wrote:
> > You seem to be not alone in wanting some special syntax for applying field
> > selectors (see other posts on this thread). H98 field selectors don't do
this,
> > they're just functions.
> >
> >
> > I'm puzzled why you want different syntax for field selectors. Can you give
> > some intuition?
>
> Here's my problems with allowing postfix application using dot for all
> functions.
>
Thank you Gábor for explaining this so clearly.
I can see that mixing prefix and postfix style would be confusing. I suppose
in other programming paradigms (like database access) record.field is regarded
as 'atomic', not as function application. And under my proposal (or SORF or
TDNR) it's atomic-ish, because the dot binds tighter than **even function
application**.
We already have in H98 field selection as function application. I'm keen not
to break that, because then I can use dot notation on H98-style records. And
I'm very keen that field selection (continue to) be equivalent to function
application, precisely so that people who prefer prefix notation can "carry on
regardless".
Do people really write code with huge pile-ups of functions prefix upon
prefix? Wouldn't that be confusing even when it's unidirectional? I've seen
some examples in other threads mixing dot notation with function composition
with user-defined operators built with a dot (like >.< ) and a sprinkling of
parentheses. They were indeed unreadable, but frankly, I don't think that was
purely down to the dot notation.
> The first problem is that mixing prefix and postfix function
> application within the same line makes it harder to read.
I can see that. As you say, it's hopeless if readers have to start in the
middle somewhere and work outwards, swerving to and fro.
If binding-dot is just (reverse) function application, I can't stop people
exploiting it for more than field selection, and some functions just 'feel'
like fields. SPJ gave the examples of:
customer.fullName -- fullName is a function to concat first ++ last
shape.area -- polymorph area overloded for each shape
And then there's:
datetime.month -- calculate month from number-of-days format
tuple.fst
string.last
name.middleInitial
address.streetNumber
polar.theta.arctan
We're on the slippery slope! Where will it end?
And now that I've found it, I so love:
customer.lastName.tail.head.toUpper -- Yay!
I notice that for prefix functions you do sometimes need a bit of trickery to
deal with partial application and inconvenient order of parameters. Of course
there's parentheses to help, but there's also a family of combinators,
especially:
($) -- loose-binding function application
(.) -- function composition
So I'm going to take your post as a challenge: can we build a family of
combinators for postfix style? The objective is to 'keep up the momentum' left
to right.
I've already been using one such:
(.$) = flip ($) -- looks combinator-ish to me!
(.$!) = flip ($!) -- strict version
customer.lastName .$ tail .$ head .$ toUpper -- Yay.$!
> The other problem is that, in order to make partial application
> convenient, you want to put your function's parameters in the order of
> least specific to most specific. If you want to make postfix
> application convenient, you have to do the reverse.
True-ish. I guess it depends how 'tight' you feel the function binds with it's
least specific parameters. What's atomic?
>
> For example, take the filter function from the Prelude:
>
> filter :: (a -> Bool) -> [a] -> [a]
>
> But for postfix function application, this latter order is the one you want:
>
> [1..10].filter even
> is a lot more intuitive than
> even.filter [1..10]
Agreed. Easy. How do you like these?:
[1..10] .$ filter even
[1..10] .$ filter even .$ sum ^ 2
[1..10] .$ filter even .$ foldr (+) 0 ^ 2
I'm looking at those thinking 'Oh yes! foldr (+) 0 is atomic-ish'.
>
> ... You'll end up with
> some people preferring postfix notation and writing their functions
> one way, other people preferring partial application and writing their
> functions the other way, and a lot of frustration when people from one
> group want to use functions written by the other.
Yeah, like little-endians vs. big-endians.
> I hope you'll agree
> that writing two versions of every function is not a satisfactory
> solution.
Absolutely! And we've a huge body of code defined in prefix form, we don't
want to re-engineer that. And there's a whole body of
mathematics/algebra/logic that uses prefix style.
>
> To finally get around to the point:
>
> All of this said, record.field is still the most readable, intuitive,
> and familiar syntax for selecting a field from a record that I know
> of. It would be nice to have it.
Indeed!
> If we restrict this postfix notation
> to only selecting fields from records,
Would you like to include 'virtual' fields like fullName or area? Or fst or
last or middleInitial?
>
> So my preferred solution is:
>
> - Selecting fields from records can be written (equivalently) using
> either prefix or postfix notation;
> - Everything else can be written only with prefix notation.
>
> My second-choice solution is to not introduce postfix notation.
>
Noted. (And from the above, you won't expect me to agree.) I guess GHC HQ gets
the final decision. Glad I'm not having to mediate.
Thank you for raising the issue so cogently.
AntC
More information about the Haskell-Cafe
mailing list