Есть что-то вроде `map2:: (i → a) → (i → b) → [i] → [(a, b)]`?
Я просто писал такие функции до map4
только потому, что они кажутся полезными:
map2 :: Functor f => (i -> a) -> (i -> b) -> f i -> f (a,b)
map2 f1 f2 = fmap $ \i -> (f1 i, f2 i)
Прежде чем продолжить map8
, я подумал, что спрошу, есть ли что-то подобное в каком-то стандартном модуле. Кажется, что Hayoo не знает никакой функции, у которой есть подпись выше.
Примечание. Я уже нашел Control.Arrow.&&&
, который сводит приведенное выше к:
map2 f1 f2 = fmap (f1 &&& f2)
Но, похоже, не существует аналогичной функции для разветвления более двух.
Ответы
Ответ 1
(->) i
является прикладным функтором, поэтому вы можете написать (&&&)
как
f &&& g = (,) <$> f <*> g
и вы можете написать map3
как
map3 f1 f2 f3 = map ((,,) <$> f1 <*> f2 <*> f3)
за исключением того, что он не короче
map3 f1 f2 f3 = map $ \i -> (f1 i, f2 i, f3 i)
Но благодаря подсказке Габриэля это короче:
map3 f1 f2 f3 = map (liftA3 (,,) f1 f2 f3)
Ответ 2
Нет стандартной функции для разветкителя более двух, хотя вы можете имитировать ее с помощью вложенных кортежей:
f :: i -> a
g :: i -> b
h :: i -> c
f &&& g :: i -> (a, b)
(f &&& g) &&& h :: i -> ((a, b), c)
Если вам не нравятся вложенные кортежи, вам нужно будет написать эту функцию самостоятельно:
fanout3 :: (i -> a) -> (i -> b) -> (i -> c) -> i -> (a, b, c)
fanout3 f g h i = (f i, g i, h i)
Как вы упомянули в своем вопросе, как только у вас есть такая функция, вы можете просто map
его:
map (fanout3 f g h) :: [i] -> [(a, b, c)]