Mengenal tipe data dasar Haskell seperti Int, Integer berpresisi arbitrari, Double, Bool, Char, String dan tuple, memahami bagaimana compiler menebak tipe lewat type inference Hindley-Milner, menulis signature eksplisit dengan ::, serta menguasai kurung dan currying pada tipe fungsi berparameter banyak.

Setelah di episode 4 kalian menulis definisi fungsi, guards, where/let, dan memahami aturan layout, saatnya memahami bahasa tipe Haskell. Jika sintaks adalah tata kalimat, tipe adalah semantiknya: tipe menentukan apa yang boleh dan tidak boleh dilakukan sebuah ekspresi, dan compiler-lah yang menegakkannya sebelum program berjalan.
Mengapa bab ini penting? Karena di Haskell, tipe adalah dokumentasi, kontrak, dan bug-detector sekaligus. Signature yang kalian tulis menjadi spesifikasi perilaku fungsi; compiler memeriksa bahwa implementasi mematuhinya. Sebagian besar waktu debugging kalian akan dihabiskan untuk "berdialog" dengan type checker — semakin paham bahasanya, semakin cepat kalian menyelesaikan masalah.
| Tipe | Deskripsi | Contoh |
|---|---|---|
Int | Bilangan bulat 64-bit (fixed width) | 42 |
Integer | Bilangan bulat presisi arbitrer (tak terbatas) | 12345678901234567890 |
Double | Floating point presisi ganda | 3.14159 |
Bool | Boolean | True, False |
Char | Satu karakter | 'a' |
String | List of Char (alias [Char]) | "halo" |
(a, b) | Tuple — pasangan nilai (heterogen) | (1, "satu") |
Pembedaan paling penting untuk bulat: Int dibatasi lebar bit (bisa overflow), sementara Integer bisa menampung angka sebesar apa pun selama memori cukup. Untuk komputasi yang butuh presisi penuh — misalnya kriptografi atau keuangan — Integer adalah pilihan aman.
Satu fakta yang menjelaskan banyak hal: String hanyalah alias dari [Char] — list berisi karakter. Ini berarti semua fungsi list (yang akan kita bahas di episode 6) langsung bekerja pada String:
halo :: String
halo = "halo"
pertama :: Char
pertama = head "halo" -- 'h'
terbalik :: String
terbalik = reverse "halo" -- "olah"head mengambil elemen pertama list, reverse membaliknya — keduanya fungsi list biasa yang "tanpa tahu" kalau list-nya berisi karakter.
Kekuatan besar Haskell: kalian tidak wajib menulis tipe. Algoritma Hindley-Milner menebaknya dari penggunaan:
addOne x = x + 1Tanyakan ke GHCi:
ghci> let addOne x = x + 1
ghci> :t addOne
addOne :: Num a => a -> aGHC menjawab Num a => a -> a — artinya: "untuk tipe a apa pun yang merupakan anggota typeclass Num, fungsi ini menerima a dan mengembalikan a". Compiler menemukan bahwa + hanya bekerja untuk tipe numerik, jadi ia meng-generalisasi tipe addOne selama memenuhi batasan itu. Inilah contoh typeclass yang akan kita bedah di episode 8.
Karena tipe ditebak umum (polymorphic), menulis signature eksplisit akan mempersempit tipe. addOne :: Int -> Int membuat fungsi hanya bekerja untuk Int — pilihan yang tepat kalau memang hanya itu yang dibutuhkan, karena compiler akan mengingatkan saat fungsi dipanggil dengan tipe lain.
Tip
Aturan praktis Haskeller: tulis signature untuk semua fungsi top-level. Type inference bekerja tanpa signature, tetapi signature menjadi kontrak yang dibaca manusia dan diperiksa compiler. Ketika refactor berantakan, compiler menunjuk baris yang melanggar kontrak.
Signature adalah deklarasi tipe eksplisit, memakai operator :: yang dibaca "bertipe":
luasPersegi :: Int -> Int
luasPersegi sisi = sisi * sisi
sapa :: String -> String
sapa nama = "Halo, " ++ nama ++ "!"++ adalah operator konkatenasi string. Perhatikan bahwa menulis signature di atas definisi adalah konvensi; compiler mengecek kesesuaian keduanya. Signature salah + definisi benar = error kompilasi — inilah yang dimaksud "tipe sebagai kontrak".
Tipe Int -> Int -> Int berarti: fungsi yang menerima Int, menghasilkan fungsi Int -> Int. Operator -> bersifat right-associative: Int -> Int -> Int dibaca Int -> (Int -> Int).
tambah :: Int -> Int -> Int
tambah x y = x + y
plusSepuluh :: Int -> Int
plusSepuluh = tambah 10plusSepuluh = tambah 10 memakai partial application: kita memberikan satu argumen dan menyimpan fungsi yang tersisa. Tanpa menulis parameter sama sekali, plusSepuluh adalah fungsi Int -> Int. Ini adalah kunci fleksibilitas pemrograman fungsional — fungsi bisa dirakit seperti bahan bangunan.
Sebaliknya, jika fungsi menerima satu argumen yang kebetulan bertipe fungsi (higher-order), tanda kurung wajib:
applyTwice :: (Int -> Int) -> Int -> Int
applyTwice f x = f (f x)Di sini (Int -> Int) dalam kurung adalah parameter pertama: applyTwice menerima fungsi, lalu menerapkan-nya dua kali. applyTwice (*2) 5 menghasilkan 20.
Tuple mengelompokkan nilai dengan tipe berbeda dalam satu nilai komposit:
user :: (String, Int)
user = ("devan", 29)
koordinat :: (Double, Double)
koordinat = (-6.2, 106.8)Tuple punya ukuran tetap (dua elemen di atas, bisa tiga, empat, dst.) dan tiap posisi punya tipe tersendiri: ("devan", 29) bertipe (String, Int), bukan (Int, String) — urutan dan tipe menentukan tipe tuple. Akses elemen pertama lewat fst dan kedua lewat snd:
nama :: String
nama = fst user -- "devan"Untuk tuple lebih dari dua elemen, pattern matching (episode 6) adalah cara yang lebih nyaman.
Int dengan Double. x + 1 gagal jika x :: Double — Haskell tidak mengubah tipe secara implisit. Konversi eksplisit memakai fromIntegral, round, floor, dan ceiling.rataRata :: [Int] -> Double
rataRata xs = fromIntegral (sum xs) / fromIntegral (length xs)applyTwice (*2) 5 membutuhkan (*2) dalam kurung; applyTwice *2 5 tidak akan terkompilasi.'halo' adalah Char (error karena lebih dari satu karakter); selalu gunakan "..." untuk String.Inti yang harus dibawa pulang:
Int (fixed width), Integer (arbitrary precision), Double, Bool, Char, String (alias [Char]), dan tuple (a, b).:t di GHCi menampilkannya.:: — ini kontrak yang diperiksa compiler.-> bersifat right-associative; a -> b -> c adalah a -> (b -> c) — dasar currying dan partial application.fromIntegral untuk angka.Di episode 6 selanjutnya kita akan membahas lists, tuples & pattern matching — list homogen [a], list comprehension, fungsi map/filter/foldl/foldr, dekonstruksi list dengan (x:xs), serta pola pada tuple dan guards dengan wildcard. Sampai jumpa di episode 6!