haskell - ¿Hay algo como `map2::(i-> a)->(i-> b)->[i]->[(a, b)]`?
arrows (2)
Acabo de escribir funciones como esta hasta map4
solo porque parecen útiles:
map2 :: Functor f => (i -> a) -> (i -> b) -> f i -> f (a,b)
map2 f1 f2 = fmap $ /i -> (f1 i, f2 i)
Antes de continuar con map8
pensé en preguntar si hay algo similar en algún módulo estándar. Parece que Hayoo no conoce ninguna función que tenga la firma anterior.
Nota: ya encontré Control.Arrow.&&&
que reduce lo anterior a:
map2 f1 f2 = fmap (f1 &&& f2)
Pero no parece haber una función similar para un fanout más de dos.
No hay una función estándar para un fanout más de dos, aunque puede simularlo utilizando tuplas anidadas:
f :: i -> a
g :: i -> b
h :: i -> c
f &&& g :: i -> (a, b)
(f &&& g) &&& h :: i -> ((a, b), c)
Si no te gustan las tuplas anidadas, tendrás que escribir esta función tú mismo:
fanout3 :: (i -> a) -> (i -> b) -> (i -> c) -> i -> (a, b, c)
fanout3 f g h i = (f i, g i, h i)
Como mencionó en su pregunta, una vez que tenga dicha función, puede map
:
map (fanout3 f g h) :: [i] -> [(a, b, c)]
(->) i
es un functor aplicativo, por lo que puede escribir (&&&)
como
f &&& g = (,) <$> f <*> g
y map3
escribir map3
como
map3 f1 f2 f3 = map ((,,) <$> f1 <*> f2 <*> f3)
excepto que no es más corto que
map3 f1 f2 f3 = map $ /i -> (f1 i, f2 i, f3 i)
Pero gracias al consejo de Gabriel, esto es más corto:
map3 f1 f2 f3 = map (liftA3 (,,) f1 f2 f3)