IO & Do Notation di Haskell
Penjelasan
Haskell adalah bahasa PURE — fungsi biasa tidak boleh punya efek samping (side effect) seperti mencetak ke layar. Tapi program NYATA butuh melakukan aksi seperti itu, jadi Haskell membungkusnya dalam tipe khusus `IO a` — nilai yang "mendeskripsikan" sebuah aksi IO yang menghasilkan tipe `a`. `main :: IO ()` artinya "main adalah aksi IO yang tidak menghasilkan nilai berguna" (`()` dibaca "unit", tipe kosong). Ketika kamu punya LEBIH DARI SATU aksi IO yang harus dijalankan berurutan (mis. cetak lalu cetak lagi), kamu butuh blok `do` — sintaks yang membiarkan beberapa aksi IO ditulis baris demi baris, terasa seperti kode imperatif biasa meski di balik layar tetap functional.
Contoh Konsep
-- Satu aksi IO saja, tidak butuh do
main :: IO ()
main = putStrLn "Halo, Haskell!"
-- Lebih dari satu aksi IO, butuh blok do
main2 :: IO ()
main2 = do
putStrLn "Baris pertama"
putStrLn "Baris kedua"
putStrLn "Baris ketiga"
-- do juga bisa mengikat hasil aksi IO ke sebuah nama dengan <-
main3 :: IO ()
main3 = do
putStrLn "Siapa namamu?"
nama <- getLine -- getLine :: IO String, hasilnya diikat ke 'nama'
putStrLn ("Halo, " ++ nama ++ "!")
Praktikum
Buat blok do di dalam main yang mencetak 3 baris teks berbeda secara berurutan memakai putStrLn.
Ketik/edit bebas di sini untuk latihan — kode ini tidak dijalankan.
Tips
`return ()` di akhir blok `do` BUKAN seperti `return` di bahasa imperatif — di Haskell, `return x` cuma membungkus `x` jadi aksi IO tanpa efek tambahan. Kalau blok `do`-mu sudah berakhir dengan aksi IO lain (misal `putStrLn`), kamu sering tidak butuh `return ()` sama sekali.