pemrograman haskell

23
Konsep Bahasa Pemrograman Pemrograman Haskell Disusun Oleh : Musofa 672011605 Danang Kurniawan 672012606 Program Studi Teknik Informatika Faktultas Teknologi Informasi Universitas Kristen Satya Wacana Salatiga 2013

Upload: shofa-dumy

Post on 19-Jan-2016

195 views

Category:

Documents


0 download

DESCRIPTION

Haskell adalah bahasa pemrograman fungsional murni. Nama bahasa pemrograman Haskell diambil dari nama seseorang matematikawan Haskell Curry

TRANSCRIPT

Page 1: Pemrograman Haskell

Konsep Bahasa Pemrograman

Pemrograman Haskell

Disusun Oleh :

Musofa 672011605

Danang Kurniawan 672012606

Program Studi Teknik Informatika

Faktultas Teknologi Informasi

Universitas Kristen Satya Wacana

Salatiga

2013

Page 2: Pemrograman Haskell

Pemrograman Haskell

Haskell merupakan bahasa pemrograman yang fungsional, malas dan murni. Ia disebut

„malas’ karena tidak mengevaluasi ekspresi-ekspresi yang digunakannya yang sebenarnya

memang tidak diperlukan untuk menentukan jawaban bagi suatu masalah. Kebalikan dari „malas‟

adalah „teliti‟ yang merupakan strategi pengevaluasian bagi kebanyakan bahasa pemrograman

(C, C++, Java, bahkan ML). Salah satu ciri dari bahasa yang teliti adalah setiap ekspresi diteliti

apakah hasil dari perhitungan tersebut penting atau tidak.(Hal ini mungkin tidak mutlak benar

seluruhnya karena adanya pengoptimalan compiler yang sering disebut dengan“eleminasi kode

mati”yang akan menghilangkan ekspresi yang tidak digunakan di program yang sering dilakukan

oleh bahasa-bahasa tersebut). Haskell disebut „murni’ karena bahasa ini tidak memperbolehkan

adanya efek samping (Efek samping adalah sesuatu yang mempengaruhi “bagian” di program.

Misalnya suatu fungsi yang mencetak sesuatu ke layar yang mempengaruhi nilai dari variabel

global. Tentu saja, suatu bahasa pemrograman yang tanpa efek samping akan menjadi sangat

tidak berguna; Haskell menggunakan sebuah system monads untuk mengisolasi semua

komputasi kotor dari program dan menampilkannya dengan cara yang aman. Haskell disebut

bahasa „fungsional’ karena evaluasi dari programnya sama dengan mengevaluasi sebuah fungsi

dalam bahasa matematika murni. Hal ini juga yang membedakannya dari bahasa standard

(seperti C dan Java) yang mengevaluasi sederetan pernyataan secara urut (inilah pola dari bahasa

terstruktur ) Yang termasuk dalam bahasa pemrograman fungsional antara lain Lisp, Scheme,

Erlang, Clean, Mercury, ML, OCaml, SQL, XSL dan lain-lain. Di antara bahasa fungsional

tersebut, Haskell merupakan bahasa yang ideal dalam banyak hal. Bahasa fungsional seperti juga

bahasa logika seperti Prolog adalah deklaratif. Kebalikannya yaitu bahasa procedural dan bahasa

yang berorientasi pada obyek adalah terstruktur. Haskell memiliki sintak yang lebih mudah

untuk dipahami daripada Lisp--bahasa turunan--(terutama bagi pemrogram yang pernah

menggunakan bahasa yang menggunakan tanda baca yang sederhana/ringan seperti Python, TCL

and REXX). Kebanyakan operatornya bersifat infix, tapi ada juga yang prefix. Pengaturan

indentasi dan modulnya sangatlah familiar dan mungkin sangat menarik, misalnya tanda kurung

bersarang yang terlalu dalam (seperti yang terlihat dalam Lisp) dihindari.

Page 3: Pemrograman Haskell

Sejarah Pemrograman Haskell

Pada bulan September tahun 1987 diadakan pertemuan dalam konferensi Bahasa

Pemrograman Fungsional dan Arsitektur Komputer atau Functional Programming Languages

and Computer Architecture (FPCA ‟87) di Portland, Oregon, untuk membicarakan keadaan yang

kurang menguntungkan di komunitas pemrograman fungsional yaitu adanya selusin bahasa

pemrograman fungsional yang murni, kesemuanya mirip dalam hal bentuk ekspresi dan

sintaknya. Telah dihasilkan suatu konsensus yang kuat dalam pertemuan itu yaitu bahwa

penyebarluasan kegunaan dari kelas bahasa fungsional ini telah dihalangi oleh kekurangan dari

kebanyakan bahasa. Telah diputuskan juga bahwa harus ada sebuah komite yang dibentuk untuk

merancang suatu bahasa yang menyediakan komunikasi gagasan baru yang lebih cepat, suatu

dasar yang stabil bagi pengembangan aplikasi nyata dan sebuah cara untuk membuat orang

tertarik menggunakan bahasa fungsional. Kemudian diciptakanlah sebuah bahasa pemrograman

fungsional yang murni yang dinamai Haskell. Nama tersebut diambil dari nama seorang ahli

logika yaitu Haskell B. Curry yang telah menciptakan banyak dasar-dasar logika bagi kita.

Tujuan utama dari komite tersebut adalah untuk merancang bahasa yang memenuhi syarat

sebagai berikut :

1. Harus cocok untuk pengajaran, penelitian dan aplikasi termasuk untuk membuat sistem

yang besar.

2. Harus seluruhnya dijelaskan melalui sintak dan semantik yang formal.

3. Harus tersedia secara bebas. Semua orang boleh mengimplementasikan bahasa tersebut

dan menyebarkannya ke siapa saja yang mereka sukai.

4. Harus didasarkan pada gagasan yang sesuai dengan konsensus umum.

5. Harus mengurangi perubahan yang tidak diperlukan dalam bahasa pemrograman

fungsional.

Komite tersebut menganggap bahwa Haskell dapat dijadikan sebagai bahan penelitian masa

depan dalam bidang rancangan bahasa dan berharap bahwa variasi bahasa akan muncul sesuai

dengan hasil percobaan. Haskell kemudian terus berkembang sejak dipublikasikan. Pada

pertengahan tahun 1997, telah ada empat rancangan bahasa yang dihasilkan (yang terbaru pada

saat itu adalah Haskell 1.4). Pada saat workshop Haskell tahun 1997 di Amsterdam, diputuskan

bahwa diperlukan varian yang stabil dari Haskell. Bahasa yang stabil ini disebut “Haskell 98”.

Page 4: Pemrograman Haskell

Haskell 98 mirip dengan Haskell 1.4, tapi ia menawarkan beberapa penyederhanaan dan

penghilangan lubang-lubang jebakan karena ketidakhati-hatian.

Setelah Haskell 98 stabil, kelihatan jelas sekali bahwa banyak program memerlukan akses ke

suatu set pustaka fungsi yang lebih banyak (yakni berhubungan dengan input/output dan

interaksi ringan dengan sistem operasi). Jika program ini menjadi fleksibel, sekumpulan pustaka

harus distandarkan juga. Sejumlah usaha dilakukan oleh komite untuk memperbaiki pustaka

Haskell 98.

Haskell

Haskell merupakan salah satu dari banyak bahasa pemrograman fungsional, seperti Lisp,

Scheme, Erlang, Clean, Mercury, ML, Ocaml, SQL, XSL, dll. Mirip dengan bahasa

pemrograman fungsional, bahasa pemrograman logical seperti Prolog merupakan bahasa

pemrograman deklaratif. Berlawanan dengan kedua kategori di atas, bahasa pemrograman

prosedural dan object-oriented masuk dalam kategori bahasa pemrograman terstruktur.

Dikatakan “terstruktur”, karena mengandung urutan perintah yang dieksekusi satu demi satu

secara strict (keras). Beberapa bahasa pemrograman seperti Python, Perl, dan Ruby melewati

batasan-batasan paradigma di atas.

Di antara bahasa pemrograman fungsional, Haskell dalam banyak hal merupakan yang

paling ideal. Haskell merupakan bahasa pemrograman fungsional murni, yang berarti jauh dari

efek samping. Bahasa pemrograman fungsional merupakan ekspresi tunggal, yang dieksekusi

dengan mengevaluasi ekspresi tersebut. Bahasa pemrograman fungsional mirip dengan

spreadsheet, di mana nilai dari tiap cell ditetapkan yang berpengaruh pada nilai dari cell lainnya.

Fokusnya adalah pada apa yang akan dihitung, bukan bagaimana proses penghitungannya.

Adapun kelebihan dari bahasa pemrograman fungsional antara lain:

1. Singkat.

Program fungsional cenderung lebih ringkas dibanding program terstruktur (2 sampai 10

kali).

2. Mudah dimengerti.

Page 5: Pemrograman Haskell

Program fungsional seringjali lebih mudah untuk dimengerti. Dalam kasus Quicksort,

tidak terlalu diperlukan pengetahuan mengenai Haskell maupun quicksort. Hal tersebut

tidak dapat terjadi pada program C, yang membutuhkan waktu untuk dimengerti, dan

sangat mudah untuk melakukan kesalahn kecil yang mengakibatkan program tidak dapat

dieksekusi.

3. Tidak ada tumpukan pada memori.

Tidak ada kemungkinan memperlakukan integer sebagai pointer, atau dilanjutkan dengan

pointer null.

4. Kode dapat digunakan kembali.

Bahasa pemrograman fungsional menggunakan polymorphism, yang akan meningkatkan

penggunaan kembali kode.

5. Pelekatan yang kuat.

Bahasa fungsional non-strict memliki fitur kuat lainnya: hanya mengevaluasi program

seperti yang diperlukan untuk menghasilkan jawaban, yang sering disebut dengan lazy

evaluation. Struktur data dievaluasi secukupnya untuk menghasilkan jawaban, dan

sebagian mungkin tidak dievaluasi sama sekali. Hal ini memungkinkan “pelekatan” untuk

menyusun bersama program yang sudah ada. Hal ini memungkinkan penggunaan

kembali program, atau potongan program lebih sering dari yang dapat dilakukan oleh

pengaturan terstruktur.

6. Abstraksi yang kuat.

Secara umum bahasa fungsional menawarkan cara-cara baru yang kuat untuk meng-

enkapsulasi abstraksi. Abstraksi mengizinkan kita untuk menentukan objek yang

pekerjaan internalnya tersembunyi. Abstraksi merupakan kunci untuk membangun

program modular yang dapat dipelihara. Satu mekanisme abstraksi yang kuat yang

terdapat dalam bahasa fungsional adalah higher-order function.

7. Manajemen memori yang terintegrasi.

Kebanyakan program rumit perlu mengalokasikan memori dinamis dari tumpukan (heap).

Setiap bahasa fungsional memudahkan pemrogram dari beban manajemen penyimpanan

Page 6: Pemrograman Haskell

tersebut. Penyimpanan dialokasikan dan diinisialisaikan secara implisit, dan diselamatkan

secara otomatis oleh kolektor sampah.

Mengapa Menggunakan Haskell

Menulis system software yang besar sangatlah sulit dan mahal. Dan bahkan untuk mengelola

system itu bisa lebih sulit dan lebih mahal. Bahasa pemrograman fungsional semacam Haskell

dapat membuatnya lebih mudah dan lebih murah. Haskell sebagai bahasa pemrograman

fungsional murni dapat :

1. Meningkatkan produktifitas programmer (Ericsson banyak memanfaatkan hasil

percobaan Haskell dalam software telephony)

2. Lebih singkat, lebih jelas dan kode-kodenya mudah dibaca

3. Errornya semakin sedikit dan reabilitynya lebih tinggi

4. Membuat jarak antara programmer dengan bahasa itu lebih pendek

5. Waktu untuk membuat program menjadi lebih singkat

Banyak alasan untuk menggunakan Haskell diantaranya adalah kita bisa menulis kode bebas

atau bugs-free code dalam waktu yang lebih singkat dibanding bahasa lainnya. Bahasa ini terus-

menerus berkembang dan kian hari makin banyak kelebihannya. Selain itu, Haskell cocok untuk

berbagai macam aplikasi.

Sebagai contoh:

Quicksort dalam Haskell:

qsort[] = []

qsort(x:xs)= qsort elts_lt_x ++ [x] ++ qsort elts_lt_greq_x

where

elts_lt_x = [y|y<-xs, y<x]

elts_greq_x = [y|y<-xs, y>= x]

Quicksort dalam C:

qsort(a, lo, hl) int a[], hi, lo;

Page 7: Pemrograman Haskell

{

int h, l, p, t;

if (lo<hi) {

l=lo;

h=hi;

p=a[hi];

do

while ((l<h) && (a[l]<=p))

l=l+1;

while ((h>l) && (a[h]>=p))

h=h-1;

if (l<h) {

t=a[l];

a[l]=a[h];

a[h]=t;

}

} while (l<h);

t=a[l];

a[l]=a[hi];

a[hi]=t;

qsort(a, lo, l-1);

qsort(a, l+1, hi);

}

}

Page 8: Pemrograman Haskell

Di samping itu yang paling penting adalah komunitas pengguna Haskell yang sangat

membantu dalam memecahkan permasalahan seputar pemrograman menggunakan Haskell.

Bahasa pemrograman ini secara konstan berkembang (bukan berarti bahasa pemrograman ini

tidak stabil, tetapi banyak perluasan yang telah ditambahkan pada beberapa compiler yang sangat

membantu pengguna) dan seringkali usul pengguna diperhatikan saat perluasan akan

diimplementasikan.

Mengapa Tidak Menggunakan Haskell

Ada dua kelemahan dari Haskell yaitu :

1. kode programnya cenderung agak lambat berkembang dibanding program yang sama

yang ditulis dalam bahasa seperti C

2. Haskell cenderung sulit untuk didebug.

Kelemahan kedua bukanlah masalah yang terlalu besar tetapi yang pertama agak

mengganggu, namun walaupun demikian CPU time selalu lebih murah daripada programmer

time dan tidak apalah jika harus menunggu sedikit lebih lama untuk melihat outputnya setelah

menyimpannya beberapa hari terhitung dari saat diprogram dan didebug. Namun Haskell

sekarang telah memiliki standard interface fungsi asing atau foreign-function interface yang

memperbolehkan kita untuk berhubungan dengan kode program yang ditulis dalam bahasa lain.

Keuntungan Haskell

Tidak ada variabel yang berubah

Salah satu dari kebiasaan pemrograman paling umum dalam pemrograman terstruktur

adalah untuk memberikan suatu nilai ke suatu variabel, kemudian memberinya suatu nilai

berbeda seperti contoh dalam bahasa C berikut ini

if (myVar==37) {...}

myVar += 2

for (myVar=0; myVar<37; myVar++) {...}

Page 9: Pemrograman Haskell

Namun dalam Haskell sangalah berbeda variabel untuk jenis ini tidak ada sama sekali.

Suatu nama bisa berupa nilai, tetapi sekali diberikan nilai, nama tersebut mewakili nilai itu di

seluruh program. Tidak boleh ada pengubahan. Dalam Haskell, " variabel" adalah kurang lebih

seperti variabel dalam persamaan matematika. Sebagai inspirasi, lihat contoh dalam persamaan

matematika di bawah ini:

10x + 5y - 7z + 1 = 0

17x + 5y - 10z + 3 = 0

5x - 4y + 3z - 6 = 0

Terlihat bahwa ada beberapa “nama” yang tidak diketahui nilainya berapa, akan tetapi yang

tidak diketahui tersebut tidak akan berubah samapai kita berhasil menemukan jawabannya.

Meniadakan efek samping

Dalam Haskell, perhitungan fungsi tidak bisa mempunyai efek samping di dalam

program itu. Kebanyakan efek samping di dalam program terstruktur mungkin jenis variabel

yang didefinisikan kembali dalam panel akhir ( baik variabel global, atau lokal, atau kamus,

daftar, atau struktur penyimpanan lain), tetapi tiap-tiap Peristiwa I/O adalah juga merupakan efek

samping. Disain baik mungkin memerlukan keluaran dan masukan itu hanya terjadi di dalam

suatu kesatuan terbatas dinamai fungsi. Sedikit pemrograman tersusun ditujukan untuk membaca

dan menulis ke STDIO, file, alat grafis, dll., disemua tempat dan dengan cara yang sukar untuk

diperkirakan. pemrograman fungsional mengandung lingkungan skrip tingkat yang lebih tinggi.

Tidak ada perulangan

Corak menarik Haskell yang lain adalah meniadakan segala konstruksi perulangan. Tidak

ada for dan tidak ada while. Tidak Ada GOTO atau branch atau jmp atau break. Orang akan

berpikir bahwa mustahil untuk mengendalikan pekerjaan suatu program tanpa konstruksi

(terstruktur) dasar seperti; tetapi membuang hal-hal ini benar-benar sungguh melegakan.

Ketiadaan perulangan sungguh sama halnya perihal tidak ada efek samping. Ketika masuk dalam

suatu perulangan maka tidak bisa mendefinisikan variabel-variabel dengan nilai yan berbeda, tak

Page 10: Pemrograman Haskell

ada yang membedakannya. Kebutuhan untuk percabangan adalah digunakan unutk membedakan

aktivitas program. Sedangkan pemrograman fungsional tidak memiliki aktivitas, hanya definisi-

definisi fungsi sehingga tidak memerlukan percabangan.tetapi tetap ada kemungkinan untuk

mensimulasikan hampir semua konstruksi perulangan umum, yang sering menggunakan kata

kunci sama seperti di bahasa yang lain, dan dalam suatu gaya yang sepertinya serupa ke

konstruksi terstruktur.

Tidak ada program order

Yang lain yang tidak dibutuhkan olah Haskell adalah program order. Satuan definisi yang

membenahi suatu program dapat terjadi dalam order manapun dan apapun juga. Untuk contoh,

ini mungkin nampak seperti suatu masalah:

Kutipan program :

-- Program excerpt

j = 1+i

i = 5

-- Hugs session after loading above program

-- Main> i

-- 5 :: Integer

-- Main> j

-- 6 :: Integer

Yang perlu dipahami dalam program seperti di atas adalah bahwa i dan j tidak diberikan

nilai-nilai, tetapi diberikan dari apa yang proses berikan. Sesungguhnya, i dan j adalah fungsi,

dan contoh di atas adalah definisi fungsi. Pada banyak bahasa pemprograman terstruktur, tidak

boleh mendefinisikan suatu fungsi lebih dari satu kali (setidaknya dalam lingkup yang sama).

Tipe Data

Page 11: Pemrograman Haskell

Sebelumnya akan dibahas dulu tipe-tipe data yang akan digunakan, yaitu Integer, Char,

dan Double, Bool, dan list.

Integer menyatakan bilangan bulat. Contoh Integer adalah -1, 0, dan 20.

Char menyatakan karakter (simbol-simbol yang digunakan untuk penulisan), yang contohnya

adalah „a‟, „?‟, dan „4‟.

Double menyatakan bilangan floating point, yaitu tipe data bilangan yang bisa melambangkan

pecahan. Contohnya adalah 3.14, 0.0, dan -1.69. Perhatikan bahwa 0 adalah Integer sedangkan

0.0 merupakan floating point. 2.0, 5.0, dan 11.0 juga merupakan floating point. Tipe data

Integer tidak akan pernah dituliskan menggunakan tanda desimal (titik), sedangkan tipe data

floating point selalu dituliskan menggunakan tanda desimal.

Bool dapat bernilai True atau False (tidak keduanya).

List sendiri secara mudahnya adalah deretan dari data-data yang tipenya sama. Contohnya

adalah [1,2,3] yang merupakan list Integer.

Karena Haskell merupakan bahasa fungsional murni, semua perhitungan dilakukan

melalui evaluasi dari ekspresi (terminologi sintaks) untuk menghasilkan nilai-nilai (entitas

abstrak yang dianggap sebagai jawaban). Setiap nilai berasosiasi dengan satu tipe (secara intuisi

tipe dapat dianalogikan sebagai himpunan nilai-nilai). Ekspresi termasuk nilai-nilai atomik

seperti integer 5, karakter „a‟, dan fungsi \x -> x+1, seperti halnya juga nilai-nilai terstruktur

seperti list [1,2,3] dan pasangan („b‟,4).

Seperti halnya ekspresi menandai nilai, ekspresi tipe merupakan terminologi sintaks yang

menandai tipe nilai. Ekspresi tipe termasuk tipe atomik Integer (integer dengan ketepatan tanpa

batas), Char (karakter), Integer->Integer (fungsi pemetaan Integer ke Integer), juga tipe

terstruktur [Integer] (list integer homogen) dan (Char,Integer) (pasangan integer dan karakter).

Semua nilai dalam Haskell adalah “first-class”- dapat dilewatkan sebagai argumen ke

fungsi, dikembalikan sebagai hasil, diletakkan dalam struktur data, dll. Tipe dalam Haskell, pada

sisi lain, bukan merupakan “first class”. Tipe dalam hal mendeskripsikan nilai, dan asosiasi dari

nilai dengan tipenya dinamakan typing. Typing dapat ditulis sebagai berikut:

Page 12: Pemrograman Haskell

5 :: Integer

„a‟ :: Char

inc :: Integer -> Integer

[1,2,3] :: [Integer]

(„b‟,4) :: (Char,Integer)

“::” dibaca “bertipe”.

Fungsi dalam Haskell biasanya digambarkan sebagai rangkaian persamaan. Sebagai

contoh fungsi inc dapat digambarkan sebagai persamaan tunggal:

inc n = n+1

Sebuah persamaan merupakan contoh dari sebuah deklarasi. Jenis lain dari deklarasi adalah type

signature declaration, di mana dapat dideklarasikan typing secara eksplisit untuk inc:

inc :: Integer -> Integer

Untuk tujuan pendidikan, jika akan diindikasikan sebuah ekspresi c1 menghasilkan atau

menurunkan ekspresi atau nilai c2, maka ditulis:

c1 c2

Sebagai contoh:

inc(inc 3) 5

Sistem tipe statis pada Haskell menggambarkan hubungan formal antara tipe dan nilai.

Sistem tipe statis meyakinkan program Haskell type safe; yaitu pemrogram aman dari kesalahan

pemilihan tipe. Sebagai contoh tidak dapat dilakukan penjumlahan 2 karakter, sehingga ekspresi

„a‟+‟b‟ merupakan penulisan yang salah. Keuntungan utama dari bahasa bertipe statis adalah

semua kesalahan/error tipe terdeteksi saat program di-compile. Tidak semua kesalahan ditangkap

oleh sistem tipe; ekspresi seperti 1/0 dapat bertipe, tetapi akan menghasilkan kesalahan pada

waktu eksekusi. Tetapi sistem tipe masih menemukan kesalahan program pada waktu compile,

yang mengizinkan compiler untuk menghasilkan kode yang lebih efisien.

Page 13: Pemrograman Haskell

Sistem tipe juga memastikan bahwa user-supplied type signature adalah benar. Dalam

kenyataannya sistem tipe pada Haskell cukup kuat untuk mengizinkan pengguna untuk

menghindari menulis type signature sama sekali; dengan kata lain sistem tipe menyimpulkan tipe

yang benar untuk pengguna.

Tipe Polymorfism

Haskell juga menyertakan tipe polimorfis – tipe yang dalam beberapa cara terukur di atas semua

tipe. Ekspresi tipe polimorfis menguraikan keluarga dari tipe-tipe. Sebagai contoh, ( a )[a]

adalah keluarga dari tipe di mana untuk setiap tipe a berisi tipe list dari a. List dari integer

(seperti [1,2,3]), list dari karakter ([„a‟,‟b‟,‟c‟]), sekalipun list dari list integer, dll, adalah

anggota dari keluarga ini. (Sebagai catatan [2,‟b‟] bukan contoh yang valid karena tidak ada tipe

tunggal yang berisi 2 dan „b‟).

List merupakan struktur data yang umum digunakan dalam bahasa fungsional, dan

merupakan sarana yang baik untuk menerangkan prinsip-prinsip dari polimorfisme. List [1,2,3]

dalam Haskell merupakan kependekan dari list 1:(2:(3:[])), di mana [] merupakan list kosong

dan : merupakan operator infix yang meletakkan argumen pertama di depan argumen kedua

(dalam hal ini list), atau dapat juga ditulis 1:2:3:[].

Sebagai contoh dari fungsi user-defined yang beroperasi pada list, pertimbangkan

masalah menghitung jumlah elemen dalam list berikut:

length :: [a] -> Integer

length [] = 0

length (x:xs) = 1 + length xs

Dari persamaan di atas terbaca: “Panjang dari list kosong adalah 0, dan panjang dari list di mana

elemen pertamanya x dan sisanya xs adalah 1 ditambah panjang dari xs.” (sebagai catatan xs

merupakan jamak dari x, dan harus dibaca demikian).

Page 14: Pemrograman Haskell

Walaupun secara intuitif, contoh di atas menyorot sebuah aspek penting dari Haskell,

yaitu pattern matching (pencocokan pola). Ruas kiri persamaan mengandung pola seperti [] dan

x:xs. Dalam sebuah fungsi aplikasi, pola-pola seperti ini dibandingkan dengan parameter aktual

(nyata) dengan cara intuitif ([] hanya cocok dengan list kosong, dan x:xs akan cocok dengan list

apa saja dengan minimal satu elemen, x dihubungkan dengan elemen pertama dan xs dengan

sisanya dalam list). Jika pencocokan sukses, ruas kanan dievaluasi dan dikembalikan sebagai

hasil dari aplikasi. Jika gagal, persamaan berikutnya akan dicoba, dan jika semua persamaan

gagal, maka hasilnya error.

Fungsi length di atas juga merupakan contoh dari sebuah fungsi polimorfis. Fungsi

tersebut dapat diterapkan pada list yang berisi elemen bertipe apa saja, sebagai contoh [Integer],

[Char], atau [[Integer]].

length [1,2,3] 3

length [„a‟,‟b‟,‟c‟] 3

length [[1],[2],[3]] 3

Berikut adalah 2 contoh fungsi polimorfis dalam list. fungsi head mengembalikan elemen

pertama dari list, fungsi tail mengembalikan semua elemen kecuali elemen pertama.

head :: [a] -> a

head (x:xs) = x

tail :: [a] -> [a]

tail (x:xs) = xs

Page 15: Pemrograman Haskell

Tidak seperti fungsi length, fungsi-fungsi di atas tidak didefinisikan untuk semua nilai yang

mungkin dari argumen mereka. Runtime error (kesalahan saat program dijalankan) akan muncul

saat fungsi-fungsi tersebut diterapkan pada list kosong.

Dengan tipe polimorfis beberapa tipe lebih umum dibanding lainnya dalam hal himpunan

nilai yang didefinisikan lebih besar. Sebagai contoh tipe [a] adalah lebih umum dari [Char].

Dengan kata lain, tipe terakhir dapat diturunkan dari sebelumnya dengan substitusi yang cocok

untuk a. Dibandingkan dengan bahasa bertipe monomorfis seperti C, polimorfisme

meningkatkan ke-ekspresif-an, dan tipe inferensi meringankan beban tipe dari pemrogram.

Tipe prinsipal (utama) dari ekspresi atau fungsi adalah tipe yang paling tidak umum,

secara intuitif, “berisi semua instan dari ekspresi”. Sebagai contoh, tipe prinsipal dari fungsi

head adalah [a] -> a; [b] -> a, a -> a.

Tipe User-Defind

Kita dapat menentukan tipe data sendiri dalam Haskell menggunakan deklarasi data.

Tipe penting yang sudah dikenal oleh Haskell adalah nilai kebenaran:

data Bool = False | True

Tipe yang didefinisikan di sini adalah Bool yang mempunyai dua nilai, yaitu True dan False.

Tipe Bool adalah sebuah contoh dari tipe konstruktor, dan True dan False adalah data

konstruktor (atau konstruktor saja).

Dengan cara yang sama kita dapat mendefinisikan tipe warna:

data Color = Red | Green | Blue | Indigo | Violet

Page 16: Pemrograman Haskell

Bool dan Color dalam contoh di atas merupakan tipe enumerasi.

Berikut contoh dari tipe dengan hanya satu data konstruktor:

data Point a = Pt a a

Karena merupakan konstruktor tunggal, tipe seperti Point sering disebut tipe tuple, karena

merupakan produk kartesian (dalam hal ini biner) dari tipe lain. Berlawanan dengan itu, tipe

multi-konstruktor seperti Bool dan Color disebut union dari tipe sum.

Point merupakan contoh dari tipe polimorfis: untuk semua tipe t, ia mendefinisikan tipe

dari titik-titik kartesian yang menggunakan t sebagai tipe koordinat. Dalam contoh sebelumnya

[] juga merupakan tipe konstruktor. Pada tipe t (bertipe apa saja) dapat diterapkan [] untuk

menghasilkan tipe baru [t]. sintaks Haskell mengizinkan [] t ditulis sebagai [t]. -> juga

merupakan tipe konstruktor; diberikan 2 tipe t dan u, t -> u merupakan tipe dari fungsi pemetaan

elemen dari tipe t ke elemen dari tipe u.

Catatlah bahwa tipe dari konstruktor data biner Pt adalah a -> a -> Point a, sehingga

yang berikut adalah valid:

Pt 2.0 3.0 :: Point Float

Pt „a‟ „b‟ :: Point Char

Pt True False :: Point Bool

Pada sisi lain, ekspresi seperti Pt „a‟ 1 tidak valid karena „a‟ dan 1 berbeda tipe.

Penting untuk membedakan antara menerapkan data konstruktor untuk menghasilkan

nilai, dan menerapkan tipe konstruktor untuk menghasilkan tipe; yang pertama terjadi saat run-

Page 17: Pemrograman Haskell

time dan bagaimana kita menghitung dalam Haskell, di mana yang terakhir terjadi saat compile-

time.

Tipe konstruktor seperti Point dan data konstruktor seperti Pt adalah dalam namespaces

terpisah. Ini memungkinkan nama yang sama untuk digunakan oleh tipe konstruktor dan data

konstruktor, seperti berikut:

data Point a = Point a a

Tipe Rekursif

Tipe dapat juga rekursif, seperti tipe dalam pohon biner:

data Tree a = Leaf a | Branch (Tree a) (Tree a)

Di sini didefinisikan tipe polimorfis pohon biner yang mana elemen-elemennya adalah node Leaf

berisi nilai dari tipe a, atau node internal (“branch”) berisi dua sub-tree (rekursif).

Saat membaca deklarasi data seperti ini, ingat bahwa Tree adalah tipe konstruktor, di

mana Branch dan Leaf adalah data konstruktor. Di samping menciptakan koneksi antara

konstruktor-konstruktor ini, deklarasi di atas mendefinisikan tipe berikut untuk Branch dan

Leaf:

Branch :: Tree a -> Tree a -> Tree a

Leaf :: a -> Tree a

Dengan contoh di atas telah didefinisikan suatu tipe yang cukup kaya untuk

mendefinisikan beberapa fungsi (rekursif) yang menggunakannya. Sebagai contoh akan

didefinisikan sebuah fungsi fringe yang mengembalikan sebuah list dari semua elemen dalam

Page 18: Pemrograman Haskell

daun dari sebuah pohon dari kiri ke kanan. Biasanya akan sangat membantu jika dituliskan

terlebih dulu tipe dari fungsi baru; dalam kasus ini tipe seharusnya Tree a -> [a]. fringe

merupakan fungsi polimorfis di mana untuk semua tipe a, memetakan pohon dari a ke list dari a.

Definisi yang tepat sebagai berikut:

fringe :: Tree a -> [a]

fringe (Leaf x) = [x]

fringe (Branch left right) = fringe left ++ fringe right

Di sini ++ merupakan operator infix yang menggabungkan dua list.

Tipe Sinonim

Untuk kenyamanan, Haskell menyediakan cara untuk mendefinisikan tipe sinonim, yaitu nama

untuk tipe yang sering dipakai. Tipe sinonim dibuat menggunakan deklarasi type. Berikut

beberapa contoh:

type String = [Char]

type Person = (Name,Address)

type Name = String

data Address = None | Addr String

Tipe sinonim tidak mendefinisikan tipe baru, tetapi memberi nama baru kepada tipe-tipe

yang sudah ada. Sebagai contoh tipe Person -> Name setara dengan (String,Address) ->

String. Nama yang baru seringkali lebih pendek dari tipe sinonimnya, tetapi itu bukan satu-

satunya tujuan dari tipe sinonim: tipe sinonim meningkatkan kemudahan membaca sebuah

program dengan menjadi lebih mnemonik. Bahkan tipe polimorfis sekalipun dapat diberi nama

baru:

Page 19: Pemrograman Haskell

type AssocList a b = [(a,b)]

Ini merupakan “tipe asosiasi” yang mengasosiasikan nilai dari tipe a dengan nilai dari tipe b.

Operator

Untuk tipe data angka, terdapat operator aritmatika untuk penjumlahan, pengurangan, perkalian,

dan pembagian. Dengan operator-operator tersebut, kita bisa menggunakan interpreter Haskell

sebagaimana menggunakan kalkulator. Inilah beberapa contohnya:

? 1 + 1

> 2

? 5 – 3

> 2

? 7 * 7

> 49

? 4 / 2

> 2.0

? (2 * 2) - (4 * 1 * 3)

> -8

? 3.14 * 2.1 * 2.1

> 13.8474

Page 20: Pemrograman Haskell

Dalam contoh-contoh di atas, tanda tanya (?) mengawali input yang kita tuliskan dan tanda lebih

besar (>) mengawali outputnya. Salah satu hal yang menarik adalah bahwa pembagian Integer

dengan Integer menghasilkan bilangan floating point. Hal ini seperti di Pascal, dan berbeda

dengan LISP (nenek moyang Haskell) dan C/C++/C#/Java.

Di Haskell, list merupakan tipe data yang fundamental. Seperti yang telah disebutkan, list hanya

bisa berisi satu tipe data (misalnya integer). Membuat list sangatlah mudah, yaitu dengan syntax

berikut:

? [1, 2, 3, 4]

> [1,2,3,4]

? [„a‟, „b‟, „c‟]

> [1,2,3,4]

? [3.14, 2.72]

> [3.14,2.72]

? []

> []

Kita bisa membuat deret aritmatika dengan mudah, misalnya:

? [1..10]

> [1,2,3,4,5,6,7,8,9,10]

Page 21: Pemrograman Haskell

? [2,4..20]

> [2,4,6,8,10,12,14,16,18,20]

Kita juga dapat membuat deret tak hingga misalnya [1,3,..], tetapi kalau itu kita lakukan maka

interpreter tidak akan pernah selesesai menuliskan anggota deret tersebut (kecuali kalau kita

hentikan).

Salah satu operasi list yang sederhana adalah penjumlahan list, contohnya:

? [1..10] ++ [21..30]

> [1,2,3,4,5,6,7,8,9,10,21,22,23,24,25,26,27,28,29,30]

Fungsi

Fungsi dapat dibuat dengan menuliskan tipenya, lalu mendefinisikannya. Misalnya:

tambahSatu :: Integer -> Integer

tambahSatu x = x + 1

Jika kita gunakan fungsinya, inilah outputnya:

? tambahSatu 5

> 6

? tambahSatu 999

> 1000

Page 22: Pemrograman Haskell

Baris yang pertama:

tambahSatu :: Integer -> Integer

berarti bahwa fungsi yang kita buat bernama tambahSatu, lalu dia menerima input sebuat

Integer dan akan mengembalikan nilai Integer. Sebetulnya jika kita tidak menentukan tipe

fungsi, interpreter akan menganalisa fungsinya untuk ditentukan tipenya. Walaupun begitu akan

lebih jelas bagi pembaca (dan juga meringankan tuga interpreter) jika tipe fungsinya dituliskan

oleh kita.

Kita bisa lihat bahwa definisi fungsinya sangat mirip dengan notasi matematika untuk fungsi

yang sama, yaitu f(x) = x + 1.

Catatan: Dalam interpreter Hugs 98, definisi fungsi harus berada di sebuah file teks dan untuk

menggunakannya kita harus meload file yang bersangkutan dari Hugs 98. File harus diberi

awalan yang menunjukkan nama modul.

Sebagai contoh, untuk menggunakan fungsi tambahSatu kita harus memiliki file teks dengan isi

sebagai berikut:

module Test where

tambahSatu :: Integer -> Integer

tambahSatu x = x + 1

Jika fungsi tersebut kita save sebagai Test.hs di folder d:\Haskell, maka untuk meloadnya dari

Hugs 98 kita harus memasukkan perintah berikut:

Page 23: Pemrograman Haskell

? :load "D:\Haskell\Test.hs"

Jika filenya kita ubah lalu kita ingin meload ulang dari Hugs 98, maka kita cukup mengetikkan

perintah berikut:

? :reload

Grafik

Dalam Haskell, kita juga dapat menggambarkan objek 3 dimensi. Penggambaran objek 3 dimensi

ini dimungkinkan karena dalam Haskell kita dapat menuliskan pemrograman