Atualmente, estou lidando com uma função que é assim:
foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)
Em outras palavras, dada uma lista, ela usa os seis primeiros elementos para algo e, se a lista tiver menos de seis elementos, será usada def
como substituta dos que estão faltando. Isso é total, mas as partes não são (exatamente como map fromJust . filter isJust
), então eu não gosto. Tentei reescrever isso para que ele não precisasse de parcialidade, e consegui:
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
Eu tecnicamente fiz o que eu quero, mas agora isso é uma bagunça gigantesca. Como posso fazer isso de uma maneira mais elegante e menos repetitiva?
case xs ++ repeat def of a:b:c:d:e:f:_ -> ...
é local o suficiente para que eu não pense duas vezes apenas em usá-lo e pular toda a maquinaria extra que as respostas existentes estão introduzindo. Geralmente, são os argumentos de globalidade mais globais (que envolvem invariantes mantidos em várias chamadas de função, por exemplo) que me deixam nervosa.
takeWithDef
não é utilizável se retornar uma lista regular, pois precisamos padronizar a correspondência com a seguinte: - / A solução adequada é o que Daniel escreveu abaixo em sua segunda resposta. uncons
só recebe o primeiro elemento, então não é tão útil.
uncons :: Default a => [a] -> (a,[a])
padrãodef
. Ou um padrãotakeWithDef
. E / ou um padrão de visualização / sinônimo de padrão. Isso requer a escrita de algum código auxiliar auxiliar, no entanto.