Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing duplication (with Applicative ((->) t), perhaps?)

I was playing around with a simple function for someone else's Stack Overflow question, and wrote the expression:

f a x ++ f a y

Obviously this is the best way to write that expression in real life, given I have all those variables in scope anyway, but I saw the duplication of f a, and thought "Hey, maybe you can remove that with the Applicative instance for functions". I wound up with:

liftA2 (++) (flip f x) (flip f y) a

which is just awful. Is there some nicer way to remove this duplication?Obviously I could also remove the duplication by binding f a to something in a where clause, but this was intended as an exercise in using built-in functions.

like image 279
amalloy Avatar asked Sep 30 '15 20:09

amalloy


3 Answers

You could do

((++) `on` f a) x y

That doesn't use Applicative, though (sorry).

like image 177
melpomene Avatar answered Oct 23 '22 00:10

melpomene


[...] maybe you can remove that with the Applicative instance for functions.

Do you have to use the Applicative instance of ((->) t)? If you just want to get rid of the duplicated f a, why not use the list monad, instead?

[x, y] >>= f a

or, equivalently,

f a =<< [x, y]

Example:

λ> let f :: Int -> Int -> [Int]; f a x = [a .. x]

λ> f 1 2 ++ f 1 3
[1,2,1,2,3]

λ> [2, 3] >>= f 1
[1,2,1,2,3]

λ> f 1 =<< [2, 3]
[1,2,1,2,3]
like image 21
jub0bs Avatar answered Oct 22 '22 23:10

jub0bs


Bikeshedding is fun! Another option would be to use the Monoid instance for functions:

(($x) <> ($y)) (f a)
like image 15
Daniel Wagner Avatar answered Oct 23 '22 01:10

Daniel Wagner