Pengalaman pengembang

HLS, pemformatan kode, hlint, dan debugger GHC 9.14.

Daftar isi

Toolchain yang mampu membangun program belum lengkap tanpa perkakas yang membuat pekerjaan sehari-hari nyaman, yaitu pemeriksaan yang berjalan saat mengetik, pemformatan yang otomatis, dan debugger yang menelusuri eksekusi. Ekosistem Haskell menyediakan ketiganya melalui Haskell Language Server, formatter seperti fourmolu, pemeriksa hlint, serta debugger yang menyertai GHC. Topik ini membahas peran masing-masing perkakas, cara memasangnya, dan kebiasaan yang membuatnya efektif.

Haskell Language Server#

Haskell Language Server, biasanya disingkat HLS, adalah layanan yang berbicara dengan editor melalui protokol Language Server Protocol, yaitu protokol yang sama dengan yang digunakan banyak bahasa lain untuk fitur editor pintar. Setelah HLS berjalan di belakang editor, tipe setiap fungsi tampil mengambang di atas kode, pemeriksaan tipe berjalan saat berkas disimpan, lompatan ke definisi dan daftar penggunaan berfungsi lintas berkas, serta autocompletion menyertakan konteks tipenya.

HLS dipasang melalui GHCup sebagaimana GHC dan Cabal pada modul pembuka jalur ini, dan versi HLS perlu disesuaikan dengan versi GHC yang digunakan proyek.

bash
# tidak-dijalankan
# pasang HLS dan jadikan sebagai versi bawaan
ghcup install hls
ghcup set hls

Perintah tersebut tidak dapat dieksekusi di lingkungan contoh jalur ini karena perintahnya memasang perangkat lunak secara interaktif, sehingga bentuknya dipaparkan sebagaimana dokumentasi GHCup. Setelah pemasangan selesai dan editor dipasangkan dengan HLS, kesalahan tipe tampil di editor tanpa perlu menjalankan cabal build terlebih dahulu, sehingga jarak antara menulis dan memeriksa memendek.

Pemformatan dan pemeriksaan kode#

Pemformatan kode Haskell didelegasikan kepada formatter, dan fourmolu adalah pilihan yang lazim. Formatter menyeragamkan tata letak, yaitu lekukan, penjajaran, dan pemenggalan baris, sehingga diskusi gaya tidak lagi menghabiskan waktu tinjauan kode. Kebiasaan yang menyertainya berupa menjalankan formatter pada berkas yang disimpan, baik melalui integrasi editor maupun perintah tunggal sebelum commit.

Pemeriksaan idiom dikerjakan hlint, yaitu alat yang membaca kode dan menyarankan penyederhanaan berdasarkan pola yang dikenalinya, misalnya lambda yang dapat diganti section atau gabungan fungsi yang dapat dirantai lebih rapi. Saran hlint tidak mengikat, sehingga setiap temuan tetap dinilai sebelum diterima, dan penerimaan yang berulang biasanya berubah menjadi kebiasaan menulis yang lebih baik.

Debugger GHCi#

GHC menyertakan debugger pada GHCi yang menelusuri eksekusi secara bertahap. Berkas berikut menjadi contohnya, dan hasil eksekusi biasanya sudah benar, tetapi debugger tetap memperlihatkan cara berhenti di tengah perhitungan dan membaca nilai yang sedang diproses.

haskell jejak-debug.hs
-- program contoh untuk debugger GHCi
jumlahKuadrat :: [Int] -> Int
jumlahKuadrat xs = sum (map kuadrat xs)
  where
    kuadrat n = n * n

main :: IO ()
main = print (jumlahKuadrat [1, 2, 3])
text Keluaran
14

Sesi debugger tidak dapat direproduksi pada lingkungan contoh jalur ini karena berlangsung interaktif di dalam prompt GHCi, sehingga bentuknya diambil dari dokumentasi resmi GHC. Setelah GHCi dibuka pada berkas tersebut, breakpoint ditempatkan melalui :break 5 yang menunjuk baris kelima, kemudian program dijalankan dan eksekusi berhenti di breakpoint dengan nilai variabelnya tampil untuk dibaca.

bash
# tidak-dijalankan
# buka sesi interaktif GHCi pada berkas contoh
ghci jejak-debug.hs

Keluaran yang tampak pada dokumentasi saat debugger berhenti di breakpoint berbentuk berikut, diambil dari contoh dokumentasi GHC pada berkas map.hs.

text Keluaran yang diharapkan
*ghci> :break 5
Breakpoint 0 activated at  map.hs:5:15-28
*ghci> map Just [1..5]
Stopped at map.hs:(4,0)-(5,12)
_result :: [b]
x :: a
f :: a -> b
xs :: [a]

Perintah lanjutannya mengikuti pola yang konsisten, yaitu :step menelusuri satu langkah ke dalam, :continue melanjutkan sampai breakpoint berikutnya, dan pengikatan _result menampung nilai yang akan dikembalikan, sehingga yang dapat ditanyakan bukan hanya di mana program berhenti, melainkan juga apa yang sedang dipegangnya. Sejak GHC 9.14, GHC juga menyediakan debugger yang berdiri sebagai alat tersendiri di luar GHCi, dan perkembangannya layak diikuti pada dokumentasi versi terkini.

Kesalahan umum#

Kesalahan pertama adalah membiarkan HLS bekerja dengan versi GHC yang berbeda dari proyek, keadaan yang muncul setelah GHC diganti melalui GHCup tanpa memperbarui HLS, dan gejalanya berupa pemeriksaan tipe di editor yang tidak cocok dengan hasil cabal build. Pemasangan ulang HLS pada versi GHC yang baru menyelesaikannya, dan pemeriksaan cepatnya berupa membandingkan nomor versi yang dilaporkan HLS dengan ghc --version.

Kesalahan kedua berupa menumpuk warning sebelum dibaca. GHC dan HLS melaporkan warning pada setiap build, dan tumpukan kecil yang diabaikan berubah cepat menjadi lapisan yang menutupi temuan penting, sedangkan kebiasaan mengosongkan warning pada setiap perubahan menjaga daftarnya tetap pendek. Kesalahan ketiga berupa menulis ulang tata letak secara manual ketika berkas tampil berantakan, pekerjaan yang hampir selalu lebih cepat diselesaikan formatter, dengan hasil yang konsisten pada seluruh berkas proyek.

Ringkasan#

  • HLS menghadirkan pemeriksaan tipe, lompatan definisi, dan pelengkapan di editor melalui Language Server Protocol, dan dipasang melalui GHCup sesuai versi GHC proyek.
  • Formatter seperti fourmolu menyeragamkan tata letak secara otomatis, sedangkan hlint menyarankan penyederhanaan idiom yang tetap dinilai sebelum diterima.
  • Debugger GHCi menelusuri eksekusi melalui :break, :step, dan :continue beserta pengikatan variabel pada titik berhenti, dan GHC 9.14 mulai menyertakan debugger yang berdiri sendiri.
  • Perkakas pendukung bekerja paling efektif apabila dipasangkan sejak proyek kecil dan versinya dijaga bersama versi GHC.

Referensi#