删除重复(使用 Applicative ((->) t),也许?)

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

我正在为别人的 Stack Overflow 问题玩一个简单的函数,并写下表达式:

f a x ++ f a y

显然,这是在现实生活中编写该表达式的最佳方式,因为无论如何我都有所有这些变量,但我看到 f a 的重复,并认为 "Hey, maybe you can remove that with the Applicative instance for functions"。我结束了:

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

这太糟糕了。有没有更好的方法来删除这个重复?显然我也可以通过将 f a 绑定到 where 子句中的某些内容来删除重复,但这是作为使用内置函数的练习。

你可以

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

不过 Applicative 没有用到(抱歉)。

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

您必须使用 ((->) t)Applicative 实例吗?如果你只是想摆脱重复的 f a,为什么不使用列表 monad 呢?

[x, y] >>= f a

或者,等价地,

f a =<< [x, y]

示例:

λ> 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]

骑自行车很有趣!另一种选择是对函数使用 Monoid 实例:

(($x) <> ($y)) (f a)

由于问题暗示了使用 Applicative 的解决方案(尽管其他答案更优雅)...

((++) <$> ($ x) <*> ($ y)) (f a)