extra icon indicating copy to clipboard operation
extra copied to clipboard

Add flip const

Open ndmitchell opened this issue 5 years ago • 9 comments
trafficstars

Sometimes you want the function which takes two arguments and ignores the first. You can write that as:

flip const
\_ x -> x
const id
\_ -> id

Assuming that thing is called f, and we pass around a WHNF f x, the first two of those will leave the x captured. But in my view, the first two are also clearer to read. I however, don't guarantee that's true, my reasoning may be wrong....

It seems like having a flipConst or other function might be useful, with the best space behaviour it can do? Or maybe the restriction to only after people seq a function is just not helpful? Is there a good name for this function? Do lambdas really reduce differently for \x y -> ... vs \x -> \y -> ...? Or does the id make it different?

CC @josephcsible who brought this up first in HLint.

ndmitchell avatar Sep 17 '20 12:09 ndmitchell

AFAIK, of all the possibilities in your post, only flip const has the problem I described, and all of the other combinations will be fine.

josephcsible avatar Sep 17 '20 13:09 josephcsible

flip = \f x y -> f y x
const = \x _ -> x
f = flip const
f = (\f x y -> f y x) (\x _ -> x)

I guess I don't see what makes that special. But certainly have no confidence that it isn't.

ndmitchell avatar Sep 17 '20 16:09 ndmitchell

Looks like your 4th line has a typo: it should be f = (\f x y -> f y x) (\x _ -> x). Anyway, the performance problem stems from flip. When you do flip f x, no matter what f is, x sticks around until the expression gets one more parameter. Your other cases are all fine because they don't use flip or any equivalent to it.

josephcsible avatar Sep 17 '20 22:09 josephcsible

I don't see why the 3rd line is a problem, but the 4th line isn't. The 4th line uses an inlined version of flip, so I don't see why it isn't equivalent.

ndmitchell avatar Nov 30 '20 18:11 ndmitchell

After a beta-reduction, f = (\f x y -> f y x) (\x _ -> x) becomes f = (\x y -> (\x _ -> x) y x). Now pass someBigThing to that, and you get (\y -> (\x _ -> x) y someBigThing). This is now equivalent to the identity function, but it unnecessarily references someBigThing.

josephcsible avatar Nov 30 '20 19:11 josephcsible

So both definitions of f have a problem? That I understand, but wasn't my understanding of your statement.

ndmitchell avatar Nov 30 '20 19:11 ndmitchell

Hmm, or maybe I have come back to this thread after too long away. I'll have a reread in the morning when I'm more fresh.

ndmitchell avatar Nov 30 '20 19:11 ndmitchell

So both definitions of f have a problem? That I understand, but wasn't my understanding of your statement.

I realize I was a bit unclear. These are fine:

\_ x -> x
const id
\_ -> id

And these are bad:

flip const
(\f x y -> f y x) (\x _ -> x)

josephcsible avatar Nov 30 '20 20:11 josephcsible

Cool, I follow now. Given it's so easy to get this wrong, I'm thinking a function that is morally flip const, but without the space leak, would be a great addition. Only question is what to name it - flipConst is nice and obvious, but maybe there's a better name someone can think of.

ndmitchell avatar Dec 13 '20 11:12 ndmitchell