Je traite actuellement une fonction qui va comme ceci:
foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)
En d'autres termes, étant donné une liste, il utilise les six premiers éléments pour quelque chose, et si la liste est inférieure à six éléments, il utilise def
comme remplaçant les éléments manquants. C'est total, mais les morceaux ne le sont pas (tout comme map fromJust . filter isJust
), donc je n'aime pas ça. J'ai essayé de réécrire ceci afin qu'il n'ait pas besoin d'utiliser de partialité, et j'ai obtenu ceci:
foo [] = foobar def def def def def def
foo [a] = foobar a def def def def def
foo [a,b] = foobar a b def def def def
foo [a,b,c] = foobar a b c def def def
foo [a,b,c,d] = foobar a b c d def def
foo [a,b,c,d,e] = foobar a b c d e def
foo (a:b:c:d:e:f:_) = foobar a b c d e f
Techniquement, j'ai fait ce que je voulais, mais maintenant c'est un gigantesque bordel. Comment puis-je le faire de manière plus élégante et moins répétitive?
case xs ++ repeat def of a:b:c:d:e:f:_ -> ...
est suffisamment local pour que je ne pense pas à deux fois à simplement l'utiliser et à sauter toutes les machines supplémentaires que les réponses existantes introduisent. Ce sont généralement les arguments de totalité plus globaux (qui impliquent des invariants maintenus sur plusieurs appels de fonction, par exemple) qui me rendent nerveux.
takeWithDef
n'est pas utilisable s'il renvoie une liste régulière, car nous devons faire correspondre ce modèle: - / La bonne solution est ce que Daniel a écrit ci-dessous dans sa deuxième réponse. uncons
obtient seulement le premier élément, donc ce n'est pas très utile.
uncons :: Default a => [a] -> (a,[a])
défautdef
. Ou un défauttakeWithDef
. Et / ou un motif de vue / synonyme de motif. Cela nécessite cependant d'écrire du code auxiliaire.