Python ve Haskell

Bu zamana kadar hep object-oriented programlama dillerinde çalışmış biri olarak Haskell’i ilk gördüğümde gerçekten çok şaşırdım. Haskell fonksiyonel bir dil. Yani programlarınızı değişkenler üzerinden atamalar yaparak değilde, matematiksel ifadeler olarak yazıyorsunuz. Tabi bazı özel durumlarda Haskell içerisinde de ufak atama benzeri işlemler yapmanız gerekebiliyor. Haskell’in kullandığı matematiksel ifadelere genel olarak lambda calculus deniliyor. Atama yapma olanağınız olmadığından işlemler genelde recursive olarak geçekleştiriliyor. Eğer sizde benim gibi fonksiyonel bir dile yabancıysanız gerçekten kafanız karışabilir.

Haskell’den haberdar olduktan sonra öğrendim ki bazı bilinen dillerde fonksiyonel programlamayı destekliyormuş. Bunların başında da tabiki hep imperative hemde object-oriented programlamayı destekleyen Python geliyor. Bunların dışında Python aynı zamanda fonksiyonel programlamayı da destekliyormuş. Fakat sadece Python değil, Microsoft Virsual Studio 2010 ile birlikte gelen F# dilide fonksiyonel programlamayı destekliyor. Hatta Java bile başka 3rd party kütüphanelerle fonksiyonel programlamayı destekliyor.

Öncelikle Haskell’i ve Python’u nasıl kuracağımıza bir bakalım. Başlamadan önce belirtmeliyim ki Eclipse Galileo kullanıyorum. Bundan dolayı ayrıca bir Haskell ya da Python geliştirme ortamı anlatmak yerine, Eclipse eklentileriyle bu dilleri Eclipse’de nasıl kullanılacağını anlatacağım. İşletim sistemi olarak da Ubuntu 10.10 x86 kullanıyor olacağım.

Kurulum

Eğer bu zamana kadar Eclipse kurmadısanız, bir an önce en güncel sürümünü indirip kurmanızı tavsiye ederim.

Ubuntu altında çalıştığımdan Python interpreter sistemimde zaten yüklü. Fakat başka bir işletim sistemi kullanıyorsanız Python interpreter’ı bu siteden indirebilirsiniz. Yeni inderecek olanlar için 2.7.xx versiyonu tavsiye ediliyor. Python 3 sürümüyle ilgili bazı problemler varmış bildiğim kadarıyla fakat ne olduklarını bende tam olarak bilmiyorum. Interpreter’ımızı yükledikten sonra Eclipse eklentisini yükleyelim.

Şimdi ise Eclipse IDE’si için PyDev eklentisini indirelim ve ayarlarını yapalım.

  • Öncelikle Eclipse-> Help -> Install New Software … seçilir ve aşağıdaki repository eklenir.
  • http://pydev.org/updates
  • Yüklenebilecek dosyaların bilgisi indirildikten sorna PyDev seçilir ve yüklenir.
  • Şimdi sadece PyDev eklentisine Python interpreter’ın sistem yolunun gösterilmesi kalıyor.
  • Bunun için Eclipse-> Windows -> Preferences seçilir ve sol taraftan Pydev genişletilir
  • Interpereter – Python seçilir ve Auto Config butonuna tıklanarak, Eclipse’in sizin için sistem yolunu bulması beklenir.
    Eğer Eclipse sizin için sistem yolunu bulamazsa “usr/lib/” yoluna bakabilirsiniz. Python derleyiciniz yüklüyse bu yolun altındaki klasörlerde göreceksiniz.

Python ve Pydev yüklemesi bu kadar. Şimdi ise Haskell interpreter ve Eclipse eklentisinin nasıl yükleneceğine bakalım.

  • Öncelikle aşağıdaki komutu çalıştırarak GHC interpreter’ını yükleyelim.
    • $ sudo apt-get install ghc6
    • Ya da eğer çok kullanılar kütüphaneleri ile birlikte falan yüklemek isterseniz
      $ sudo apt-get install haskell-platform
  • GHC yüklendikten sonra sıra Eclipse eklentimize geliyor yani EclipseFP 2.0
  • Yine Eclipse-> Help -> Install New Software … seçilir ve aşağıdaki repository eklenir.
  • http://eclipsefp.sf.net/updates ve 2.0.2 versiyonu yüklenir.
  • Haskell içinde GHC’nin sistem yolunu vermemiz gerekiyor.
  • Bunun için Eclipse-> Windows -> Preferences ve sol taraftan Haskell genişletilir
  • Haskell Implementations seçilerek GHC’nin sistem yolu eklenir.
    Benim makinem için sistem yolu “/usr/lib/ghc-6.12.1/bin”

Şimdi her iki programlama dilimizde Eclipse ortamlarıyla beraber kurulmuş oldu. Şimdi ise benim Advanced Programming dersinde gördüğüm ve Haskell: The Craft of Functional Programming, 2nd ed., Simon Thompson kitabında anlatılan örneğin bir benzerini anlatmaya çalışalım.

Satranç Atı

Kitapta bahsi geçen ASCII karakterlerle oluşturulmuş ve horse.txt dosyasında kayıtlı satranç atı resmini okuyan ve bunun üzerinde işlemler yapan bir örnek. Örnetteki at şu şekilde ve horse.txt dosyası içerisinde kayıtlı.

horse.txt

…….##…..
…..##..#….
…##…..#…
..#…….#…
..#…#…#…
..#…###.#…
.#….#..##…
..#…#…….
…#…#……
….#..#……
…..#.#……
……##……

Bu şekil üzerinde noktaların beyaz diyez işaretlerinin siyah olduğunu varsayılım. İki tane fonksiyon ya da method yazılacak bir tanesi y eksenine göre tersine alacak bir taneside beyazları siyah, siyahları beyaz yapacak. Haskell’de ve Pythonda fonksiyonel programlama açısından bu iki işlemin nasıl yapıldığına bakalım.

Haskell

Haskelde öncelikle projemizi yaratmamız gerekiyor. Bunun için Eclipse -> New Project deyip, burdan Haskell project‘i seçiyoruz. Projemizin adı PictureInHs olsun. Daha sonra Haskell Perspective‘ini aktif hale getirip kodumuzu yazmaya başlıyoruz. Proje menüsünden kendi yarattığımız projeyi bulup src klasörürünün altına bakıyoruz ve Main.hs dosyasının zaten yaratılmış olduğunu görüyoruz. Bu dosyayı aşağıdaki gibi değiştiriyoruz

Main.hs


module Main where

type Picture = [String]

draw :: Picture -> IO ()
draw pic = (putStr . concat . map (++"n")) pic

flipV :: Picture -> Picture
flipV pic = (map reverse) pic

invertPixel :: Char -> Char
invertPixel c = if c == '.' then '#' else '.'

invert :: Picture -> Picture
invert pic = (map (map invertPixel)) pic

main::IO()
main = do
horseData <- readFile "horse.txt"
horse <- return (lines horseData)

draw horse
putStrLn "Vertical Flip"
draw (flipV horse)

putStrLn "Inverting picture items"
draw (invert horse)

Daha sonra önceden yaratığımız horse.txt dosyasını, Eclipse içinde PictureInHs projesinin altına kopyalıyoruz. Projemizi “GHCi” olarak çalıştırdığımızda, konsolda bizden girdi bekleyen bir ekran göreceğiz. Buraya main yazıp, çalıştırdığımızda, aşağıdaki ekran çıktılarını görebileceğiz.

Python

Şimdi ise, yine fonksiyonel şekilde, hibrid bir dil olan Python altında nasıl yapacağımıza bakalım. Python’un hibrid özelliğinide kullanmak için, öncelikle bir Picture Class’ı yaratalım ki bu bakımdan object-oriented olsun. Fakat istediğimiz işlemleri yapacak olan fonksiyonları, fonksiyonel şekilde yazalım ve bunları ekrana bastıralım.

Bunun için öncelikle Eclipse -> New deyip, bir Python Project yaratalım.  Fazedelim ki adı PictureInPy olsun.Bu seferde Pydev Perspective geçelim. Daha sonra projenin src klasörünün altına gelip bir Python Module yaratalım. Farzedelim ki bu modlun adıda picture.py olsun.

picture.py


# OBJECT-ORIENTED WITH FUNCTIONAL METHODS

class Picture:
def __init__(self, filename):
f = open(filename)
 self.data = f.read().splitlines()
f.close()

def drawVertical(self):
print('n'.join(self.flipV()))

def drawInvert(self):
print('n'.join(self.invert()))

def draw(self):
print('n'.join(self.data))

def flipV(self):
return map(lambda line: line[::-1], self.data)

def invert(self):
return [''.join(map(lambda c: '#' if c == '.' else '.', line))
for line in self.data]

print("\n Object Oriented with using Functional Methods \n")

horse = Picture('horse.txt')
horse.draw()

print "Vertical Flip"
horse.drawVertical()

print "Inverting picture items"
horse.drawInvert()

Şimdi daha önce hazırlamış olduğumuz horse.txt dosyasını, projemizin src klasörünün altına kopyalıyoruz.Hazırladığımız kodu çalıştırdığımızda aşağıdaki ekran çıktılarını elde edeceğiz.

Ekran Çıktıları

…….##…..
…..##..#….
…##…..#…
..#…….#…
..#…#…#…
..#…###.#…
.#….#..##…
..#…#…….
…#…#……
….#..#……
…..#.#……
……##……
Vertical Flip
…..##…….
….#..##…..
…#…..##…
…#…….#..
…#…#…#..
…#.###…#..
…##..#….#.
…….#…#..
……#…#…
……#..#….
……#.#…..
……##……
Inverting picture items
#######..#####
#####..##.####
###..#####.###
##.#######.###
##.###.###.###
##.###…#.###
#.####.##..###
##.###.#######
###.###.######
####.##.######
#####.#.######
######..######

Referanslar

Son olarak bu yazıyı hazırlarken yararlandığım kaynaklar

  • Haskell: The Craft of Functional Programming, 2nd ed.
    Addison Wesley, 1999, ISBN 0-201-34275-8
  • Aldığım, İleri Programlama,  dersimin kaynakları. SoruceForge

End Of Line