Ответ 1
Вы могли бы сделать
((++) `on` f a) x y
Это не использует Applicative
, хотя (извините).
Я играл с простой функцией для кого-то другого вопроса о переполнении стека и написал выражение:
f a x ++ f a y
Очевидно, что это лучший способ написать это выражение в реальной жизни, учитывая, что у меня есть все эти переменные в области видимости, но я видел дублирование f a
и думал: "Эй, может быть, вы можете удалить это с помощью аппликативного экземпляр для функций". Я закончил с:
liftA2 (++) (flip f x) (flip f y) a
что просто ужасно. Есть ли какой-нибудь лучший способ удалить это дублирование? Очевидно, я мог бы также удалить дублирование, привязав f a
к чему-то в предложении where
, но это было предназначено как упражнение при использовании встроенных функций.
Вы могли бы сделать
((++) `on` f a) x y
Это не использует Applicative
, хотя (извините).
[...] возможно, вы можете удалить это с помощью аппликативного экземпляра для функций.
Вам нужно использовать экземпляр Applicative
((->) t)
? Если вы просто хотите избавиться от дублированного f a
, почему бы не использовать монаду списка вместо?
[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]
Bikeshedding - это весело! Другой вариант - использовать экземпляр Monoid
для функций:
(($x) <> ($y)) (f a)
Так как вопрос намекнул на решение с использованием аппликативного (хотя другие ответы более элегантны)...
((++) <$> ($ x) <*> ($ y)) (f a)