
Hi, It's nice to write functions in point free style: f = sort . nub But sometimes I have to add an extra case, on a certain value: f [] = [1] f = sort . nub But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to: f [] = [1] f x = (sort . nub) x i.e. lift the arities to the longest argument list. Is there a reason this isn't done? Thanks Neil

That eta-expansion desugaring would lose sharing. Offhand, I don't know of
a desugaring that would do the trick and preserve sharing. Any ideas? -
Conal
On Jan 13, 2008 3:12 PM, Neil Mitchell
Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Thanks
Neil _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

G'day all.
Quoting Conal Elliott
That eta-expansion desugaring would lose sharing. Offhand, I don't know of a desugaring that would do the trick and preserve sharing. Any ideas?
How about this? f = let body = sort . nub in \xs -> case xs of [] -> [1] (_:_) -> body I suspect we're well out of the territory of mere "desugaring" here, though. Cheers, Andrew Bromage

Hi Conal,
On 1/13/08, Conal Elliott
That eta-expansion desugaring would lose sharing.
Ah, that will be it.
1. Equations with different arities more often signal bugs than correct intentions.
I don't believe that. I suspect the type system will mop these up.
2. It's highly misleading.
Again, I don't believe that. Your argument holds for why we shouldn't have multiple equations for definition, not that they should all be the same arity.
Offhand, I don't know of a desugaring that would do the trick and preserve sharing. Any ideas? -
f = let body = sort . nub in \xs -> case xs of [] -> [1] (_:_) -> body
Compared to other desugarings in Haskell, this one is positively tame! I quite like the idea of permitting equations to have different arities. It removes restrictions, makes things more regular etc. Thanks Neil

Neil Mitchell writes:
I quite like the idea of permitting equations to have different arities. It removes restrictions, makes things more regular etc.
More regular??? My goodness... Of course, it removes restrictions. But in the history of humanity rarely the removal of restrictions made things more regular! Sometimes it is useful, but not where it "for free" gives you more opportunities to make bugs. I wonder whether f = g and f x = g x attributes *always* the same type to both variants of f... Jerzy Karczmarczuk

On 13 Jan 2008, at 5:38 PM, jerzy.karczmarczuk@info.unicaen.fr wrote:
Neil Mitchell writes:
I quite like the idea of permitting equations to have different arities. It removes restrictions, makes things more regular etc.
More regular??? My goodness... Of course, it removes restrictions. But in the history of humanity rarely the removal of restrictions made things more regular! Sometimes it is useful, but not where it "for free" gives you more opportunities to make bugs. I wonder whether f = g and f x = g x attributes *always* the same type to both variants of f...
A related variant of this is trivial: f x = x f x y = x y I don't know if eliminating that last argument has similar properties in practice or not. OTOH, the question is only one of eta-expanding until you get a number of arguments we already /know/ the function takes. jcc

G'day all.
Quoting Neil Mitchell
I don't believe that. I suspect the type system will mop these up.
As previously noted, anything involving undefined (thanks to seq) is not equivalent. While undefined is arguably uncommon, error most certainly isn't: f1 (x:xs) = {- something -} f1 [] = error "empty list" -- add an argument, to get... f2 (x:xs) y = {- something -} f2 [] = error "empty list" f2 is type-correct, but is subtly different from f1, both semantically and (I think) performance-wise. On sharing: It's not generally appreciated, but in GHC, there's a subtle difference between: g x y = let z = p x in q x y z and: g x = \y -> let z = p x in q x y z the difference being that in the latter, the definition of z can be let-floated: g x = let z = p x in \y -> q x y z GHC does not float lets over lambdas if it would "break" a group of function arguments. Any proposed desugaring would have to either come up with a better rule than this, or find a way to preserve it. Cheers, Andrew Bromage

G'day all.
Quoting Neil Mitchell
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell.
I don't know why Haskell does it specifically, but here's why I like the behaviour: 1. Equations with different arities more often signal bugs than correct intentions. One common situation is adding an argument to a function, and accidentally leaving one equation out. 2. It's highly misleading. This: f [] = [1] f = sort . nub suggests that f is (sort . nub), which is most decidedly is not. By forcing you to add the argument: f [] = [1] f xs = sort . num $ xs it reminds you more strongly that what you're actually writing is a shorthand for this: f [] = [1] f xs@(_:_) = sort . num $ xs Cheers, Andrew Bromage

"Neil Mitchell"
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Most likely not, there are being made up right now. Because f = sort.nub is different from f x = (\x -> sort.nub x) or f = sort.nub.id or f = sort.nub.id.id.id.id.id.id , and such behaviour would confuse the hell out of me as well as seriously hurt my sense of semantic aesthetics, even if it's just no-ops. Or the same lambda term, which is exactly my point. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

Achim Schneider
Most likely not, there are being made up right now.
s/there/they/
f x = (\x -> sort.nub x)
s/x// -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On 13 Jan 2008, at 4:15 PM, Achim Schneider wrote:
"Neil Mitchell"
wrote: i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Most likely not, there are being made up right now.
I'm glad you are capable of ever so nobly assigning the purest imaginable motives to the designers of Haskell. You are an inspiration to us all. jcc

Jonathan Cast
On 13 Jan 2008, at 4:15 PM, Achim Schneider wrote:
"Neil Mitchell"
wrote: i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Most likely not, there are being made up right now.
I'm glad you are capable of ever so nobly assigning the purest imaginable motives to the designers of Haskell. You are an inspiration to us all.
Most likely not. I'm only assigning good taste. There might be some evil conspiracy about warping people's heads somewhere, after all. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

"Neil Mitchell"
Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Answer #2: Because you can't write f x = case x of [] -> [1] -> sort.nub -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On 13 Jan 2008, at 5:27 PM, Achim Schneider wrote:
"Neil Mitchell"
wrote: Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Answer #2:
Because you can't write
f x = case x of [] -> [1] -> sort.nub
But why not? Treating case as syntax sugar for a higher-order function, so that all binding occurrences of lambdas in the unsugared code are associated with lambdas, is a good thing, and offers a natural way of desugaring the above, one case at a time. jcc

Jonathan Cast
On 13 Jan 2008, at 5:27 PM, Achim Schneider wrote:
"Neil Mitchell"
wrote: Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Answer #2:
Because you can't write
f x = case x of [] -> [1] -> sort.nub
But why not?
Because arities aren't lifted to the longest argument list.
Treating case as syntax sugar for a higher-order function, so that all binding occurrences of lambdas in the unsugared code are associated with lambdas, is a good thing, and offers a natural way of desugaring the above, one case at a time.
What about f x = [1] f - = sort.nub ? You could also do things like f - x = (foo x).bar with it. No more rewriting of pointfree code because of added arguments... -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On 13 Jan 2008, at 5:49 PM, Achim Schneider wrote:
Jonathan Cast
wrote: On 13 Jan 2008, at 5:27 PM, Achim Schneider wrote:
Answer #2:
Because you can't write
f x = case x of [] -> [1] -> sort.nub
But why not?
Because arities aren't lifted to the longest argument list.
I think you lost the point of my question...
Treating case as syntax sugar for a higher-order function, so that all binding occurrences of lambdas in the unsugared code are associated with lambdas, is a good thing, and offers a natural way of desugaring the above, one case at a time.
What about
f x = [1] f - = sort.nub
?
You could also do things like
f - x = (foo x).bar
with it. No more rewriting of pointfree code because of added arguments...
So `-' as a pattern means `implicitly apply the RHS to whatever this pattern matches'? I like it. jcc

Jonathan Cast
On 13 Jan 2008, at 5:49 PM, Achim Schneider wrote:
Jonathan Cast
wrote: On 13 Jan 2008, at 5:27 PM, Achim Schneider wrote:
Answer #2:
Because you can't write
f x = case x of [] -> [1] -> sort.nub
But why not?
Because arities aren't lifted to the longest argument list.
I think you lost the point of my question...
I'm glad you are capable of ever so nobly assigning the purest imaginable motives to me. You are a true inspiration.
Treating case as syntax sugar for a higher-order function, so that all binding occurrences of lambdas in the unsugared code are associated with lambdas, is a good thing, and offers a natural way of desugaring the above, one case at a time.
What about
f x = [1] f - = sort.nub
?
You could also do things like
f - x = (foo x).bar
with it. No more rewriting of pointfree code because of added arguments...
So `-' as a pattern means `implicitly apply the RHS to whatever this pattern matches'? I like it.
Yes. I suppose _> is a better idea, or something else beginning with _, as the rest of the characters could be functions. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

Neil Mitchell wrote:
Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
In addition to the sharing problem, consider f True x = x f False = undefined Because of seq, the second equation is not equivalent to the eta-expanded f False x = undefined x Roman

Hello Neil, Monday, January 14, 2008, 2:12:52 AM, you wrote:
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
Is there a reason this isn't done?
this may be also due an error, and in most cases it actually will be due an error. then it makes type inference trickier and will led to very strange error messages instead of simple "different amount of arguments". so, we will buy power but lose simplicity -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

There is no technical reason for this. It's a matter of taste. As someone
else pointed out, different arities is usually a bug.
-- Lennart
On Jan 13, 2008 3:12 PM, Neil Mitchell
Hi,
It's nice to write functions in point free style:
f = sort . nub
But sometimes I have to add an extra case, on a certain value:
f [] = [1] f = sort . nub
But now these equations have different arities, and its rejected by Haskell. Why does this not simply desugar to:
f [] = [1] f x = (sort . nub) x
i.e. lift the arities to the longest argument list.
Is there a reason this isn't done?
Thanks
Neil _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (9)
-
Achim Schneider
-
ajb@spamcop.net
-
Bulat Ziganshin
-
Conal Elliott
-
jerzy.karczmarczuk@info.unicaen.fr
-
Jonathan Cast
-
Lennart Augustsson
-
Neil Mitchell
-
Roman Leshchinskiy