11
votes

Zipping avec rembourrage dans Haskell

Quelques fois, je me suis retrouvé à vouloir un zip dans Haskell qui ajoute du remplissage à la liste plus courte au lieu de tronquer le plus long. C'est assez facile pour écrire. ( monoïde fonctionne ici ici, mais vous pourriez également simplement passer les éléments que vous souhaitez utiliser pour le rembourrage.) XXX

Cette approche devient laide lorsque vous essayez de Définir zippad3 . J'ai tapé ce qui suit puis réalisé que bien sûr, cela ne fonctionne pas: xxx

à ce stade, j'ai triché et juste utilisé longueur pour choisir La liste la plus longue et les coussinets les autres.

suis-je surpluée sur une façon plus élégante de faire cela, ou est quelque chose comme zippad3 déjà défini quelque part?


0 commentaires

4 Réponses :


19
votes

Que diriez-vous de la tête et de de la queue de la queue (nommé suivant et repos dans mon exemple ci-dessous)? < Pré> xxx

essai d'essai: xxx

sa sortie: xxx


0 commentaires

12
votes

Ce modèle revient beaucoup. Une solution que j'ai apprise de Paul Chiusano est la suivante:

 *Main> zipPad3 ["foo", "bar", "baz"] [2, 4, 6, 8] [True, False] "" 0 False
 [("foo",2,True),("bar",4,False),("baz",6,False),("",8,False)]


0 commentaires

3
votes

Il y a des moments où vous voulez pouvoir appliquer une fonction différente à la queue plutôt que de simplement fournir mempty code> ou zéros manuels également: xxx pré>

i Utilisez l'ancien lorsque je fais quelque chose comme zipwithtail (+) code> et le premier quand j'ai besoin de faire quelque chose comme zipwithtail (* b) (A *) (\ da dB -> a * db + b * da) code> puisque le premier peut être beaucoup plus efficace que l'alimentation une valeur par défaut dans une fonction, et celle-ci un peu donc. p>

Cependant, si vous vouliez simplement faire une version plus succincte de ce que vous avez, vous pouvez probablement se tourner vers Mapaccuml, mais ce n'est pas plus clair. et le ++ peut être coûteux. P>

zipPad as bs = done $ mapAccumL go as bs
    where go (a:as) b = (as,(a,b))
          go [] b = ([],(mempty,b))
          done (cs, both) = both ++ fmap (\x -> (x, mempty)) cs


0 commentaires

4
votes

Un moyen plus simple de le faire est avec peut-être code>. Je vais illustrer avec Edward's Formulation plus générale:

import Data.Maybe
import Control.Applicative

zipWithTails l r f as bs = catMaybes . takeWhile isJust $
    zipWith fMaybe (extend as) (extend bs)
  where
    extend xs = map Just xs ++ repeat Nothing
    fMaybe a b = liftA2 f a b <|> fmap l a <|> fmap r b


0 commentaires