Real World Haskell, bab 4, halaman 98 dari cetakan bertanya apakah words
dapat diimplementasikan menggunakan lipatan, dan ini juga pertanyaan saya:
Apa itu mungkin? Jika tidak, mengapa? Jika ya, bagaimana?
Saya datang dengan berikut ini, yang didasarkan pada gagasan bahwa setiap non-spasi harus ditambahkan ke kata terakhir dalam daftar output (ini terjadi di otherwise
penjaga), dan bahwa ruang harus memicu penambahan kata emtpy ke daftar keluaran jika belum ada (ini ditangani di if
- then
- else
).
myWords :: String -> [String]
myWords = foldr step [[]]
where
step x yss@(y:ys)
| x == ' ' = if y == "" then yss else "":yss
| otherwise = (x:y):ys
Jelas solusi ini salah, karena spasi spasi pada string input menghasilkan satu string kosong terkemuka di daftar output string.
Pada tautan di atas, saya telah melihat ke beberapa solusi yang diusulkan untuk pembaca lain, dan banyak dari mereka bekerja mirip dengan solusi saya, tetapi mereka umumnya "pasca-proses" output flip, misalnya dengan tail
memasukkannya jika ada adalah string terkemuka yang kosong.
Pendekatan lain menggunakan tupel (sebenarnya hanya berpasangan), sehingga lipatan berurusan dengan pasangan dan dapat dengan baik menangani ruang terkemuka / trailing.
Dalam semua pendekatan ini, foldr
(atau lipatan lain, fwiw) bukan fungsi yang memberikan hasil akhir dari kotak; selalu ada hal lain dengan harus menyesuaikan output entah bagaimana.
Oleh karena itu saya kembali ke pertanyaan awal dan bertanya apakah itu benar-benar mungkin untuk diterapkan words
(dengan cara yang benar menangani trailing / spasi / spasi berulang) menggunakan lipatan. Dengan menggunakan lipatan, maksud saya bahwa fungsi lipatan harus merupakan fungsi terluar:
myWords :: String -> [String]
myWords input = foldr step seed input