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

Interesting reduction not caught by hlint. #110

Open
sheganinans opened this issue Jan 16, 2015 · 9 comments
Open

Interesting reduction not caught by hlint. #110

sheganinans opened this issue Jan 16, 2015 · 9 comments

Comments

@sheganinans
Copy link

So I have this function:

-- "Dual" of map, takes an object and a list of functions
-- and applies the object to each function in the list.
pam :: a -> [a -> b] -> [b]
pam a (f:fs) = f a : pam a fs
pam a [] = []

I was able to reduce it to:

pam :: a -> [a -> b] -> [b]
pam a = map (\f -> f a)

Sadly hlint didn't catch this reduction(Although it's able to catch a whole bunch of other reductions in my code any other day!), maybe this might lighten the way for a whole set of new reductions? Thanks for the awesome tool!

@ndmitchell
Copy link
Owner

Thanks for the bug report. Running your example, I get:

Sample.hs:4:1: Error: Use map
Found:
   pam a (f : fs) = f a : pam a fs
   pam a [] = []
Why not:
  pam a fs = map (\ f -> f a) fs

That's using version 1.9.16. Do you see any suggestions for your original input?

@sheganinans
Copy link
Author

Oops, so I guess it seems when the function has a wildcard instead of a named variable is when it fails.

This works:

pam :: a -> [a -> b] -> [b]
pam a (f:fs) = f a : pam a fs
pam a [] = []

This doesn't:

pam :: a -> [a -> b] -> [b]
pam a (f:fs) = f a : pam a fs
pam _ [] = []

@ndmitchell
Copy link
Owner

I have a custom recogniser for these types of expression, it just needs generalizing a little. Three examples which don't match but which should are:

pam :: a -> [a -> b] -> [b]
pam a (f:fs) = f a : pam a fs
pam _ [] = []

pam2 :: a -> [a -> b] -> [b]
pam2 a (f:fs) = f a : pam2 a fs
pam2 _ _ = []

pam3 :: a -> [a -> b] -> [b]
pam3 a (f:fs) = f a : pam3 a fs
pam3 b _ = []

@sheganinans
Copy link
Author

Interesting! Seems like you know about it and this issue is probably redundant. On my end it's really not a game-ending issue, so no reason to keep this thing around. Thanks for the speedy replies!

Well either way thanks a bunch for this super great project! I can't imagine life without it!

@ndmitchell
Copy link
Owner

Nope, I only investigated after your report, and I'll use this ticket to record the cases I should still do better.

@sheganinans
Copy link
Author

Oh! Sounds great!

@mishun
Copy link

mishun commented Feb 5, 2016

Should hlint further suggest

pam a = map ($ a)

or even

pam = map . flip ($)

?

@sheganinans
Copy link
Author

Yes, I would agree if generalize is turned on, it would be good to have those suggestions recommended.

@ndmitchell
Copy link
Owner

The final map . flip ($) seems pretty confusing to my eye - HLint used to go that far with point-free operations, but generally it doesn't make code more readable in general.

For reducing \ f -> f a, it's certainly a hint I could add, and then HLint when run twice would do the replacement in two steps. At the moment I don't have it though, since it feels a little complex - it's in the ballpark of what I think would be reasonable though.

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

3 participants