Saat ini saya sedang berurusan dengan fungsi yang berjalan seperti ini:
foo = (\(a:b:c:d:e:f:_) -> foobar a b c d e f) . (++ repeat def)
Dengan kata lain, diberikan daftar, ia menggunakan enam elemen pertama untuk sesuatu, dan jika daftar itu kurang dari enam elemen, ia menggunakan def
sebagai pengganti untuk yang hilang. Ini total, tetapi potongan-potongan itu tidak (hanya suka map fromJust . filter isJust
), jadi saya tidak suka itu. Saya mencoba menulis ulang ini sehingga tidak perlu menggunakan keberpihakan, dan mendapatkan ini:
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
Secara teknis saya melakukan apa yang saya inginkan, tetapi sekarang ini adalah kekacauan yang sangat besar. Bagaimana saya bisa melakukan ini dengan cara yang lebih elegan dan kurang berulang?
case xs ++ repeat def of a:b:c:d:e:f:_ -> ...
cukup lokal sehingga saya tidak akan berpikir dua kali tentang hanya menggunakannya dan melewatkan semua mesin tambahan jawaban yang ada memperkenalkan. Secara umum, argumen totalitas global (yang melibatkan invarian yang dipelihara di beberapa fungsi panggilan, misalnya) membuat saya gugup.
takeWithDef
tidak dapat digunakan jika mengembalikan daftar reguler, karena kita perlu mencocokkan pola itu: - / Solusi yang tepat adalah apa yang ditulis Daniel di bawah ini dalam jawaban keduanya. uncons
hanya mendapat elemen pertama, jadi itu tidak berguna.
uncons :: Default a => [a] -> (a,[a])
yang defaultnyadef
. Atau defaulttakeWithDef
. Dan / atau pola tampilan / sinonim pola. Ini membutuhkan penulisan beberapa kode pembantu pembantu.