Mengenal Lebih Jauh Type Signature di Haskell
Wisnu Adi Nurcahyo 15 Februari 2017
Type signature merupakan bagian dari type theory yang mana merupakan salah satu bagian dasar di dunia pemrograman. Sadar atau tidak, type signature juga ada di bahasa pemrograman seperti C/C++. Type signature atau kadang disebut juga type annotation sederhananya merupakan tempat kita mendefinisikan input, output, jumlah argument, serta tipe data yang diterima argument tersebut di sebuah function, subroutine, atau method. Tulisan ini hanya akan membahasa type signature di bahasa pemrograman Haskell.
Coba perhatikan potongan function berikut ini.
increment :: Integer -> Integer increment n = n + 1
Pada function di atas, bagian increment :: Integer -> Integer
merupakan apa yang disebut dengan type signature. Bagian ini memberikan informasi kepada kita apa-apa saja yang boleh menjadi input dan apa yang akan menjadi output. Contoh kasus di atas memberikan informasi kepada kita bahwa function tersebut memiliki satu argument berupa Integer dan akan memberikan output berupa Integer.
Type signature sangat membantu kita untuk mengetahui "identitas" dari function tersebut sehingga kita tidak perlu melakukan tracing untuk mengetahui arah berjalannya sebuah function. Dilihat dari nama function dan type signature-nya saja, kita sudah sedikit mengetahui apa yang akan dikerjakan function tersebut.
Type Inference
Sebelum mulai masuk ke bahasan type signature di bawah, perlu diketahui bahwa ada type inference. Maksud dari type inference adalah kita tidak perlu mendefinisikan tipe data karena compiler akan mencoba menentukannya sendiri. Tapi, type signature membuat program yang kita buat menjadi lebih aman dan lebih readable.
Type Signature tanpa Argument
Di Haskell, kita bisa mendefinisikan tipe data dari sebuah equation (di bahasa lain, variable) dan sebuah function.
version :: String version = "0.0.1-alpha"
Pada contoh di atas, bagian version :: String
merupakan type signature yang mendefinisikan tipe data apa yang diaplikasikan ke function tersebut. Perlu diingat bahwa contoh di atas adalah sebuah function yang tidak memiliki argument, bukan equation.
fun :: Int -> String fun x = let num = mod x 2 :: Int in if num == 0 then "Even" else "Odd"
Pada contoh di atas, bagian let num = mod x 2 :: Int
merupakan apa yang disebut dengan equation. Dan bagian :: Int
merupakan type signature-nya. Type signature tersebut dapat memperjelas tipe data apa yang diaplikasikan. Apabila tidak sesuai, compiler akan melakukan protes.
Type Signature dengan Argument
Type signature dengan argument tidak akan kita jumpai di sebuah equation. Perhatikan potongan kode berikut ini.
fun :: Int -> String fun x = let num = mod x 2 :: Int in if num == 0 then "Even" else "Odd"
Pada contoh di atas, bagian fun :: Int -> String
memiliki sebuah argument (input) berupa Int dan keluaran (output) berupa String. Cara membacanya sangat sederhana. Bagian paling akhir setelah tanda ->
adalah bagian output. Bagian setelah tanda ::
dan sebelum bagian output adalah semua argument-nya.
fun :: Int -> String fun1 :: String -> String -> [Integer] fun2 :: [String] -> [Integer] -> String -> IO ()
- Pada function
fun
, terdapat sebuah argument berupa Int dan keluarannya berupa String. - Pada function
fun1
, terdapat dua buah argument yaitu String dan String. Keluarannya berupa List dari Integer atau direpresentasikan sebagai[Integer]
. - Pada function
fun2
, terdapat tiga buah argument yaitu List dari String, List dari Integer, dan String. Keluarannya berupa actionIO ()
.
Catatan: IO ()
pada nomor tiga maksudnya input-output atau di dalam Haskell disebut sebagai "Dunia Luar". Artinya, fungsi tersebut akan memberikan sesuatu ke dunia luar (karena posisinya sebagai keluaran).
Type Variable
Pada Haskell, tidak jarang kita melihat sebuah type signature seperti fun :: a -> a
atau snd :: (a, b) -> b
. Tipe data apa itu a
dan b
? Itulah type variable. Type variable merupakan sebuah tipe data yang dapat berupa apa saja atau biasa kita tulis *
untuk menyatakan semuanya boleh. Alasan kenapa semua tipe data di Haskell ditulis kapital pada huruf pertamanya adalah karena adanya type variable.
Type Classes
Type classes sederhananya merupakan sebuah kumpulan dari tipe data dan operasinya. Untuk contoh, perhatikan potongan kode berikut.
class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool
Kita dapat baca kode tersebut sebagai berikut.
Eq
merupakan sebuah type classes dengan satu parameter yaitua
.- Untuk setiap
a
yang ingin menjadi instance dariEq
harus mendefinisikan semua fungsi di atas yaitu(==)
dan(/=)
dengan type signature yang "sejenis".
Contohnya untuk Int
menjadi (==) :: Int -> Int -> Bool
dan (/=) :: Int -> Int -> Bool
. Well, di bagian ini kita hanya mencoba mengenal type classes. Untuk tulisan secara mendalamnya mungkin di lain kesempatan.
Kembali ke bahasan type signature, kita mungkin akan menemukan type signature yang mengandung type classes seperti show :: Show a => a -> String
. Bagian Show a
sebelum tanda =>
adalah apa yang disebut dengan type class constraint. Bagian tersebut memberitahu kita bahwa function show
menggunakan type classes Show
untuk argument a
.
Mengaplikasikan Function di Type Signature
Di Haskell, kita bisa mendefinisikan sebuah type signature seperti foldl :: (a -> b -> a) -> a -> [b] -> a
. Bagian (a -> b -> a)
merupakan definisi bahwa argument pertama merupakan sebuah aplikasi dari function.
main = print $ foldl (+) 0 [1..10]
Dari kode tersebut, (+)
merupakan function yang diaplikasikan. Berdasarkan type signature-nya yaitu (a -> b -> a)
, function tersebut akan melakukan operasi yang membutuhkan dua argument. Argument pada (+)
diambil dari 0
dan [1..10]
. 0
adalah a
di argument ke-2 pada function foldl
, dan [1..10]
adalah [b]
.
Ya, seperti itulah apa-apa saja yang perlu kita ketahui mengenai type signature di bahasa pemrograman Haskell. Sampai jumpa di tulisan yang berikutnya. Apabila ada yang kurang jelas, silakan tanyakan di kotak komentar. Atau, apabila ada yang harus dikoreksi, tuliskan koreksinya di kotak komentar agar tidak ada yang "tersesat". Terima kasih!