Attualmente ho a che fare con una funzione che va così:
foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)
In altre parole, dato un elenco, utilizza i primi sei elementi per qualcosa e, se l'elenco è lungo meno di sei elementi, utilizza def
come supporto per quelli mancanti. Questo è totale, ma i suoi pezzi non sono (proprio come map fromJust . filter isJust
), quindi non mi piace. Ho provato a riscrivere questo in modo che non abbia bisogno di usare alcuna parzialità, e ho ottenuto questo:
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
Tecnicamente ho fatto quello che volevo, ma ora è un casino gigantesco. Come posso farlo in un modo più elegante e meno ripetitivo?
case xs ++ repeat def of a:b:c:d:e:f:_ -> ...
sia abbastanza locale da non pensarci due volte sul solo usarlo e saltare tutti i macchinari extra che le risposte esistenti stanno introducendo. Sono in genere gli argomenti di totalità più globali (che coinvolgono invarianti mantenuti attraverso molteplici chiamate di funzioni, ad esempio) che mi rendono nervoso.
takeWithDef
non è utilizzabile se restituisce un elenco regolare, poiché dobbiamo modellare la corrispondenza in questo modo: - / La soluzione corretta è quella che Daniel ha scritto di seguito nella sua seconda risposta. uncons
ottiene solo il primo elemento, quindi non è così utile.
uncons :: Default a => [a] -> (a,[a])
valore predefinitodef
. O un defaulttakeWithDef
. E / o un sinonimo di pattern / pattern di visualizzazione. Ciò richiede tuttavia la scrittura di un codice ausiliario ausiliario.