Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flip const #69

Open
ndmitchell opened this issue Sep 17, 2020 · 9 comments
Open

Add flip const #69

ndmitchell opened this issue Sep 17, 2020 · 9 comments

Comments

@ndmitchell
Copy link
Owner

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.

@josephcsible
Copy link
Contributor

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.

@ndmitchell
Copy link
Owner Author

ndmitchell commented Sep 17, 2020

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.

@josephcsible
Copy link
Contributor

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.

@ndmitchell
Copy link
Owner Author

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.

@josephcsible
Copy link
Contributor

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.

@ndmitchell
Copy link
Owner Author

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

@ndmitchell
Copy link
Owner Author

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.

@josephcsible
Copy link
Contributor

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)

@ndmitchell
Copy link
Owner Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants