在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):joom/zor-yoldan-haskell开源软件地址(OpenSource Url):https://github.com/joom/zor-yoldan-haskell开源编程语言(OpenSource Language):开源软件介绍(OpenSource Introduction):
Zor Yoldan Haskell
İçindekiler:Tüm geliştiricilerin Haskell öğrenmesi gerektiğine inanıyorum. Herkesin süper Haskell ninjası olması gerektiğini düşünmüyorum, ama herkes Haskell'in sahip olduğu farklı yönleri görmeli; Haskell öğrenmek zihninizi acar. Anaakım diller aynı temelleri paylaşırlar:
Ama Haskell çok farklıdır. Bu dil daha önceden hiç duymamış olduğum bir sürü kavram kullanıyor. Bu kavramların çoğu daha iyi bir programcı olmanızda yardımcı olacaktır. Haskell öğrenmek zor olabilir, benim için öyleydi. Bu yazıda ben öğrenirken eksik olan şeyleri size sunmaya çalışacağım. Bu yazıyı takip etmek zor olacak ve bunu bilerek yapıyorum; Haskell öğrenmenin kısayolu yoktur, zordur ve çaba ister. Ama bunun iyi bir şey olduğuna inanıyorum; Haskell, zor olduğu için ilginç. Haskell öğrenmenin klasik yolu şu iki kitabı okumaktır. İlk önce "Learn You a Haskell" (Haskell Öğrenin) ve sonrasında da "Real World Haskell" (Gerçek Dünyada Haskell). Ben de bunun doğru yol olduğuna inanıyorum. Haskell'in doğru düzgün öğrenmek için, bu kitapları ayrıntılı şekilde okumalısınız. Tersi şekilde, bu yazı Haskell'in ana konularının oldukça kısa ve yoğun bir özeti. Kendim Haskell öğrenirken ihtiyaç duyup bulamadığım bazı bilgileri de ekledim. Bu yazının beş bölümü var:
1. Giriş1.1. KurulumAraçlar:
1.2. KorkmayınHaskell hakkındaki pek çok kitap/makale az bilinen bir formülü (quick sort, Fibonacci, vs.) yazmakla başlıyor, bense tam tersini yapacağım. İlk önce size Haskell'in süper güçlerini göstermeyeceğim. Haskell ve diğer programlama dilleri arasındaki benzerliklerle başlayacağım. Zorunlu "Merhaba Dünya" programıyla başlayalım. main = putStrLn "Merhaba Dünya!" Çalıştırmak için, kodu
Doğrudan kaynak kodunu da indirebilirsiniz. Aşağıdaki komutların hemen altında linki görüp,
01_basic/10_Introduction/00_hello_world.lhs 01_basic/10_Introduction/10_hello_you.lhs Şimdi, adınızı soran ve aldığı cevapla size "Merhaba" diyen bir program yazalım: main = do
print "Adiniz nedir?"
name <- getLine
print ("Merhaba " ++ name ++ "!") Öncelikle, bunu birkaç imperatif dildeki benzer programlarla karşılaştıralım: # Python
print "Adiniz nedir?"
name = raw_input()
print "Merhaba %s!" % name # Ruby
puts "Adiniz nedir?"
name = gets.chomp
puts "Merhaba #{name}!" // In C
#include <stdio.h>
int main (int argc, char **argv) {
char name[666]; // <- musibetli sayi!
// Adim 665 karakterden fazlaysa ne olacak?
printf("Adiniz nedir?\n");
scanf("%s", name);
printf("Merhaba %s!\n", name);
return 0;
} Yapı aynı, ama söz dizimsel farklılıklar var. Bu yazının ana kısmı bu farkların sebebini açıklamak üzerine olacak. Haskell'de bir Şimdilik, Haskell'in anaakım imperatif dillere benzer görünebileceğini hatırlamanız yeterli. 01_basic/10_Introduction/10_hello_you.lhs 01_basic/10_Introduction/20_very_basic.lhs 1.3. Haskell'e GirişDevam etmeden önce, Haskell'in bazı temel özelliklerinin farkına varmanız gerekiyor. FonksiyonelHaskell fonksiyonel bir dildir. Eğer imperatif bir dilde geçmişiniz varsa, yeni bir sürü şey öğrenmeniz gerekiyor. Umarım bu yeni kavramlar size imperatif dillerde program yazarken bile yardımcı olur. Akıllı Statik Tip SistemiTip sistemi, SaflıkGenellikle fonksiyonlarınız dış dünyada bir şeyi değiştirmeyecekler. Bu demek oluyor ki, bir değişkenin değerini değiştiremeyecekler, kullanıcıdan girdi alamayacaklar, ekrana yazı yazamayacaklar, veya bir füzeyi ateşleyemeyecekler. Diğer yandan, paralellik sağlamak çok kolay olacak. Haskell nerede yan etkilerin olduğunun ve nerede kodunuzun saf olduğunun ayrımını çok açık bir şekilde yapar. Ayrıca, programınız hakkında mantık yürütmek de çok daha kolay olur. Çoğu hata, kodunuzun saf kısmında engellecektir. Daha da ötesi, Haskell'de saf fonksiyonlar temel bir kural izlerler:
TembellikTembellik, genelde alışılmadık bir dil tasarım tercihidir. Haskell'de varsayılan olarak her şey sadece ihtiyaç olduğunda hesaplanır / işlenir. Bunun sonuçlarından biri de sonsuz yapıları işlemek için çok mükemmel bir yol sunmasıdır. Son uyarı da Haskell kodunu nasıl okumanız gerektiğiyle ilgili. Benim için, bilimsel makaleleri okumak gibi. Bazı kısımları çok açık, ama bir formül gördünüzde odaklanın ve yavaşça okuyun. Ayrıca, Haskell öğrenirken, garip söz dizimsel detayları anlamamanız gerçekten önemli değil. Ama eğer 1.3.1. Fonksiyon tanımıŞu şekilde fonksiyon tanımlamaya alışmış olabilirsiniz: C'de: int f(int x, int y) {
return x*x + y*y;
} JavaScript'te: function f(x,y) {
return x*x + y*y;
} Python'da: def f(x,y):
return x*x + y*y Ruby'de: def f(x,y)
x*x + y*y
end Scheme'de: (define (f x y)
(+ (* x x) (* y y))) Son olarak, Haskell yolu da budur: f x y = x*x + y*y Tertemiz. Parantez yok, Unutmayın, Haskell fonksiyonları ve tipleri sıkça kullanır. Bu yüzden, onları tanımlamak oldukça kolaydır. Söz dizimi, özellikle öyle düşünülmüştür. 1.3.2. Tip örneğiZorunlu olmamasına rağmen, fonksiyonlar için tip bilgisi genellikle ayrıca girilir. Zorunlu değildir, çünkü derleyici sizin için çıkarım yapacak kadar akıllıdır. Yine de tipleri yazmak iyi bir fikirdir, çünkü kodun anlaşılmasına yardımcı olur. Bakalım nasıl oluyormuş: -- Tipleri belirtmek icin :: isaretini kullaniyoruz
f :: Int -> Int -> Int
f x y = x*x + y*y
main = print (f 2 3)
01_basic/10_Introduction/20_very_basic.lhs 01_basic/10_Introduction/21_very_basic.lhs Şimdi bunu deneyelim: f :: Int -> Int -> Int
f x y = x*x + y*y
main = print (f 2.3 4.2) Şu hatayı almış olmalısınız:
Sorun şu: 01_basic/10_Introduction/21_very_basic.lhs 01_basic/10_Introduction/22_very_basic.lhs Çözümü de şu: f x y = x*x + y*y
main = print (f 2.3 4.2) Çalışıyor! Ne şanslıyız ki, her tip için yeni bir fonksiyon tanımlamak zorunda değiliz. Örneğin Peki hangi tipi belirtmeliydik? Haskell'in bizim için bulduğu tipi görmek için
Hi? Bu garip tip de neyin nesi?
İlk önce, sağdaki
Yani Buna bazen parametrik çokşekillilik (parametric polymorphism) de deniyor. Hayatta her istediğinizin olması gibi bir şey. Genellikle
Tip sınıfları güçlü bir dil yapısıdır. Onlarla inanılmaz güçlü şeyler yapabiliriz. Buna daha sonra tekrar değineceğiz. Sonuç olarak, Diyelim ki Evet, garip. Aslında Haskell'de hiçbir fonksiyonun gerçekten iki argümanı yoktur. Onun yerine, her fonksiyonun sadece bir argümanı vardır. Ama hatırlamalıyız ki iki argüman almakla, bir argüman alıp ikinci argümanı bir parametre olarak alan bir fonksiyon döndürmek denk şeylerdir. Daha açık olmak gerekirse, f :: Num a => a -> a -> a
g :: Num a => a -> a
g = f 3
g y ⇔ 3*3 + y*y Fonksiyonlar için bir notasyon daha var. Lambda notasyonu isimsiz fonksiyonlar yaratmamıza olanak sağlar. Bunlara anonim fonksiyonlar diyoruz. Aynı şeyi lambda notasyonuyla şöyle de yazabilirdik: g = \y -> 3*3 + y*y Burada Eğer fonksiyonel programlamaya alışık değilseniz beyniniz yanmaya başlamış olmalı. Artık gerçek bir uygulama yazma zamanı. 01_basic/10_Introduction/22_very_basic.lhs 01_basic/10_Introduction/23_very_basic.lhs Ama ondan önce, tip sisteminin beklediğimiz gibi çalıştığını doğrulayalım: f :: Num a => a -> a -> a
f x y = x*x + y*y
main = print (f 3 2.4) Çalışıyor, çünkü 01_basic/10_Introduction/23_very_basic.lhs 01_basic/10_Introduction/24_very_basic.lhs Eğer fonksiyonumuzu farklı tiplerle çalışmaya zorlarsak, hata verecektir: f :: Num a => a -> a -> a
f x y = x*x + y*y
x :: Int
x = 3
y :: Float
y = 2.4
main = print (f x y) -- calismayacak, cunku tip x ≠ tip y Derleyici hata veriyor. İki parametre de aynı tipten olmak zorunda. Eğer bunun kötü bir fikir olduğunu ve derleyicinin sizin için bir tipten diğerine dönüşümü yapması gerektiğini düşünüyorsanız, bu müthiş (ve komik) videoyu mutlaka izlemelisiniz: WAT 01_basic/10_Introduction/24_very_basic.lhs 2. Temel HaskellBu kısma yalnızca göz gezdirmenizi tavsiye ediyorum. Her zaman yararlanacağınız bir kaynak gibi düşünün. Haskell'in birçok özelliği vardır. Burada da pek çoğu eksik. Eğer notasyon garip gelirse tekrar buraya dönün. İki ifadenin denk olduğunu belirtmek için 2.1. NotasyonAritmetik3 + 2 * 6 / 3 ⇔ 3 + ((2*6)/3) MantıksalTrue || False ⇒ True
True && False ⇒ False
True == False ⇒ False
True /= False ⇒ True (/=) esit degildir operatorudur Üslü Sayılarx^n herhangi bir n integral tipi icin (Int veya Integer olarak anlayin)
x**y herhangi bir y sayi tipi icin (ornegin Float)
Evet! Ayrıca rasyonel sayılar da var! Ama önce
Listeler
Karakter DizileriHaskell'de
Demetler (Tuple)Bir ikili demetin tipi -- Tum bu demetler gecerlidir
(2,"foo")
(3,'a',[2,3])
((2,"a"),"c",3)
fst (x,y) ⇒ x
snd (x,y) ⇒ y
fst (x,y,z) ⇒ HATA: fst :: (a,b) -> a
snd (x,y,z) ⇒ HATA: snd :: (a,b) -> b Parantezlerle Başa ÇıkmakBazı parantezlerden kurtulmak için -- Aslinda:
f g h x ⇔ (((f g) h) x)
-- $ isareti kendisinden ifadenin sonuna
-- kadar olan parantezin yerine gecer
f g $ h x ⇔ f g (h x) ⇔ (f g) (h x)
f $ g h x ⇔ f (g h x) ⇔ f ((g h) x)
f $ g $ h x ⇔ f (g (h x))
-- (.) kompozisyon fonksiyonu
(f . g) x ⇔ f (g x)
(f . g . h) x ⇔ f (g (h x)) 01_basic/20_Essential_Haskell/10a_Functions.lhs 2.2. Fonksiyonlar için Faydalı NotasyonlarHatırlatma: x :: Int ⇔ x Int tipinde herhangi bir deger alabilir
x :: a ⇔ x herhangi bir tip olabilir
x :: Num a => a ⇔ x Num tip sinifina dahil olan
herhangi bir a tipi olabilir
f :: a -> b ⇔ f a'dan b'ye bir fonksiyondur
f :: a -> b -> c ⇔ f a'dan (b→c)'ye bir fonksiyondur
f :: (a -> b) -> c ⇔ f (a→b)'den c'ye bir fonksiyondur Hatırlayın ki bir fonksiyonu tanımlamadan önce tipini belirtmek zorunlu değil. Haskell genelde tip çıkarımını sizin için kendisi yapar. Ama genelde tipleri belirtmek iyi uygulama olarak görülür. |