5
\$\begingroup\$

Every so often I have a function of type a -> b and a function of type b -> b -> c and I would like a function of type a -> a -> c. For example if I wanted to check the second element of each two tuples were equal

snd :: (a , b) -> b
(==) :: Eq a => a -> a -> Bool

And I want something of type

Eq b => (a, b) -> (c, b) -> Bool

The best way I have found to do this so far is

f g z=(.g).z.g

Which is ok, but it feels unneccessarily complex for something that is this simple. The pointfree representation is even worse:

flip=<<((.).).(.).flip(.)

Additionally it feels like this idiom should be representable with some sort of abstraction (it feels a lot like (<*>)). I attempted to find a replacement by abstracting our functions to functors, the result is not very enlightening

flip=<<(fmap.).fmap.flip fmap ::
  Functor f => f a -> (a -> a -> b) -> f (f b)

Is there a shorter way to express this idea? Particularly the pointfree version?

\$\endgroup\$
  • 4
    \$\begingroup\$ There is on but you need to import Data.Function. \$\endgroup\$ – flawr Dec 22 '19 at 18:02
1
\$\begingroup\$

I think eta-reduction is severely overrated. I see a lot more attempts at eta-reduction in the wild than I think is reasonable.

So it is in this case: eta-reducing this function is not helpful, I think. It's much more readable and elegant in its full form:

f :: (a -> a -> c) -> (a -> b) -> b -> b -> c
f g h a b = g (h a) (h b)

On a related note, such function exists in the standard libraries. It's called on, and the idea is to use it in infix form, so that it almost reads like English:

eqAmounts = (==) `on` amount
cmpNames = compare `on` name
| improve this answer | |
\$\endgroup\$
  • 5
    \$\begingroup\$ Welcome to the site. I will say that "readability" and "elegance" are not worth a whole lot here. The reason eta reduction is popular for golfing is that point free functions don't require costly declarations. The on function that you and flawr pointed out is nice and short though. \$\endgroup\$ – Ad Hoc Garf Hunter Dec 22 '19 at 18:44
  • 2
    \$\begingroup\$ I see. Thank you for pointing out. I will unsubscribe from this site. \$\endgroup\$ – Fyodor Soikin Dec 22 '19 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.