68 votes

Haskell: comment mapper un tuple?

En Haskell, je peux facilement mapper une liste:

 map (\x -> 2*x) [1,2]
 

me donne [2,4] . Existe-t-il une fonction "mapTuple" qui fonctionnerait comme ça?

 mapTuple (\x -> 2*x) (1,2)
 

avec le résultat étant (2,4) .

88voto

Rotsor Points 6987

Une solution assez courte et sans point:

 mapTuple = join (***)
 

Nécessite les modules Control.Monad et Control.Arrow .

51voto

Boris Points 2390

La recherche au Hoogle donne pas de correspondances exactes pour (a -> b) -> (a, a) -> (b, b), qui est le type dont vous avez besoin, mais il est assez facile à faire soi-même:

mapTuple :: (a -> b) -> (a, a) -> (b, b)
mapTuple f (a1, a2) = (f a1, f a2)

Note, vous devez définir une nouvelle fonction pour les 3-n-uplets, 4-n-uplets etc - bien qu'un tel besoin peut être un signe que vous n'êtes pas à l'aide de n-uplets comme ils ont été conçus, En général, les n-uplets contenir des valeurs de différents types, de sorte que de vouloir appliquer une fonction unique pour toutes les valeurs n'est pas très commun.

33voto

Landei Points 30509

Vous pouvez utiliser un bifunctor :

 import Control.Monad
import Data.Bifunctor

join bimap (2*) (1,2)
 

Cela fonctionne non seulement pour les paires, mais pour un certain nombre d'autres types, par exemple pour Either .

23voto

Riccardo Points 6035

Vous pouvez utiliser les flèches du module Control.Arrow pour composer des fonctions qui travaillent sur des n-uplets.

Prelude Control.Arrow> let f = (*2) *** (*2)
Prelude Control.Arrow> f (1,2)
(2,4)
Prelude Control.Arrow> let f' = (*2) *** (*3)
Prelude Control.Arrow> f (2,2)
(4,4)
Prelude Control.Arrow> f' (2,2)
(4,6)

Votre mapTuple devient alors

mapTuple f = f *** f

Si votre question vous a demandé pour une fonction qui parcourt les tuples de l'arbitraire arité, alors je crains que vous ne pouvez pas parce qu'ils ont des types différents (par exemple le n-uplet types (a,b) et (a,b,c) sont totalement différentes et indépendantes).

12voto

Peter Wortmann Points 1861

Pour ajouter une autre solution à cet ensemble coloré ... Vous pouvez également mapper des n-uplets arbitraires à l'aide de la programmation générique de Scap-Your-Boilerplate . Par exemple:

 import Data.Data
import Data.Generics.Aliases

double :: Int -> Int
double = (*2)

tuple :: (Int, Int, Int, Int)
tuple = gmapT (mkT double) (1,2,3,4)
 

Notez que les annotations de types explicites sont importantes, car SYB sélectionne les champs par type. Si l'on crée un type d'élément de tuple Float , par exemple, il ne sera plus doublé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X