Essentiellement, je souhaite effectuer l'opération suivante: [1, 2, 3, 4, 5, 6, 7] -> [3, 7, 11, 7]
Dans l'exemple ci-dessus, l'élément à la fin de la liste est laissé seul car il n'y a rien avec quoi il peut être ajouté car la liste est de longueur impaire.
Je voulais transformer la liste en une liste de tuples comme [1, 2, 3, 4] -> [(1,2), (3,4)] puis effectuer l'addition sur chaque tuple, mais je ne pouvais pas comprendre comment faire cela, et je n'étais pas sûr que cela fonctionnerait avec une liste de longueur étrange.
Il existe sûrement un moyen d'ajouter tous les deux éléments dans une liste.
3 Réponses :
Un moyen simple de le faire est d'utiliser une définition récursive de base:
combinePairs :: (a -> a -> a) -> [a] -> [a] combinePairs _ [] = [] combinePairs _ [x] = [x] combinePairs _ (x:y:list) = f x y : combinePairs list sumPairs :: Num a => [a] -> [a] sumPairs = combinePairs (+)
Cependant, si vous souhaitez le faire en combinant des fonctions existantes, vous pouvez rechercher dans hoogle [a] -> [(a,a)]
( https://hoogle.haskell.org/?hoogle=%5Ba%5D+-% 3E +% 5B% 28a% 2Ca% 29% 5D & scope = set% 3Astackage ) pour voir s'il existe des fonctions pertinentes.
Malheureusement, il ne semble pas y en avoir. Certaines fonctions que vous pourriez écrire, si vous vouliez quelque chose de plus compositionnel, sont:
sumPairs :: Num a => [a] -> [a] sumPairs = map getSum . mergePairs . map Sum
Ou, si vous vouliez être encore plus générique
pairUp :: Monoid a => [a] -> [(a,a)] pairUp [] = [] pairUp [x] = [(x, mempty)] pairUp (x:y:list) = (x,y) : pairUp list mergePairs :: Monoid a => [a] -> [a] mergePairs = map (uncurry (<>)) . pairUp
puis
pairUp :: Num a => [a] -> [(a,a)] pairUp [] = [] pairUp [x] = [(x, 0)] pairUp (x:y:list) = (x,y) : pairUp list sumPairs :: Num a => [a] -> [a] sumPairs = map (uncurry (+)) . pairUp
Ou même
sumPairs :: Num a => [a] -> [a] -- first, we deal with the base case sumPairs [] = [] -- next we deal with the odd length list base case sumPairs [x] = [x] -- now we can recurse! sumPairs (x:y:list) = (x+y) : sumPairs list
En utilisant votre premier exemple, si je voulais changer la déclaration de fonction pour être quelque chose comme paires :: (Integer -> Integer -> Integer) -> [Integer] -> [Integer] et au lieu de sommer, effectuez un (+), ( -), (*), etc. opération. Comment changer la définition?
Tant pis, je l'ai compris! Je passe juste dans _ avec la liste vide et la liste impaire, puis passe dans f avec le fond de cas, puis fais sumPairs f list pour le morceau de récursivité. En fait, très simplement!
Pour ce problème, je pense que je reviendrais à la récursivité explicite:
sumPairs :: Num a => [a] -> [a] sumPairs (x:y:ys) = x+y:sumPairs ys sumPairs xs = xs
Sympa et simple: s'il y a au moins deux éléments, additionnez-les puis répétez pour faire le reste. Sinon (ce qui signifie qu'il y a zéro ou un élément), retournez simplement la même liste que vous avez.
Alors, que se passe-t-il exactement ici? Je suis encore assez nouveau dans Haskell, donc visualiser certaines de ces fonctions est assez difficile.
Très court
map sum . chunksOf 2