Reputation: 6798
I just wrote functions like this up to map4
just because they seem useful:
map2 :: Functor f => (i -> a) -> (i -> b) -> f i -> f (a,b)
map2 f1 f2 = fmap $ \i -> (f1 i, f2 i)
Before I continue to map8
i thought I'd ask if there is something similar in some standard module. Hayoo doesn't seem to know any function that has the signature above.
Note: I already found Control.Arrow.&&&
which reduces the above to:
map2 f1 f2 = fmap (f1 &&& f2)
But there doesn't seem to be a similar function for a fanout more than two.
Upvotes: 15
Views: 3236
Reputation: 12010
(->) i
is an applicative functor, so you can write (&&&)
as
f &&& g = (,) <$> f <*> g
and you could write map3
as
map3 f1 f2 f3 = map ((,,) <$> f1 <*> f2 <*> f3)
except that it isn't shorter than
map3 f1 f2 f3 = map $ \i -> (f1 i, f2 i, f3 i)
But thanks to Gabriel's tip, this is shorter:
map3 f1 f2 f3 = map (liftA3 (,,) f1 f2 f3)
Upvotes: 18
Reputation: 35099
There is no standard function for a fanout more than two, although you can simulate it using nested tuples:
f :: i -> a
g :: i -> b
h :: i -> c
f &&& g :: i -> (a, b)
(f &&& g) &&& h :: i -> ((a, b), c)
If you don't like nested tuples then you will have to write this function yourself:
fanout3 :: (i -> a) -> (i -> b) -> (i -> c) -> i -> (a, b, c)
fanout3 f g h i = (f i, g i, h i)
Like you mentioned in your question, once you have such a function you can then just map
it:
map (fanout3 f g h) :: [i] -> [(a, b, c)]
Upvotes: 11