Obecnie mam do czynienia z funkcją, która wygląda następująco:
foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)
Innymi słowy, biorąc pod uwagę listę, używa pierwszych sześciu elementów do czegoś, a jeśli lista ma mniej niż sześć elementów, używa def
jako stand-in dla brakujących. To jest suma, ale kawałki nie są (tak jak map fromJust . filter isJust
), więc nie lubię tego. Próbowałem przepisać to, aby nie trzeba było używać żadnej stronniczości, i otrzymałem to:
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
Technicznie zrobiłem to, co chciałem, ale teraz jest to gigantyczny bałagan. Jak mogę to zrobić w bardziej elegancki i mniej powtarzalny sposób?
case xs ++ repeat def of a:b:c:d:e:f:_ -> ...
jest na tyle lokalny, że nie zastanawiałbym się dwa razy po prostu o używaniu go i pomijaniu wszystkich dodatkowych mechanizmów, które wprowadzają istniejące odpowiedzi. Na ogół denerwują mnie bardziej globalne argumenty totalności (które obejmują niezmienniki utrzymywane w wielu wywołaniach funkcji, np.).
takeWithDef
nie nadaje się do użycia, jeśli zwraca regularną listę, ponieważ musimy dopasować wzór, że: - / Właściwym rozwiązaniem jest to, co Daniel napisał poniżej w swojej drugiej odpowiedzi. uncons
dostaje tylko pierwszy element, więc nie jest to tak przydatne.
uncons :: Default a => [a] -> (a,[a])
domyślną wartośćdef
. Lub domyślnietakeWithDef
. I / lub synonim wzorca widoku / wzorca. Wymaga to jednak napisania pomocniczego kodu pomocnika.