Haskell - Hızlı Kılavuz

Haskell, sembolik hesaplama ve liste işleme uygulamalarını işlemek için özel olarak tasarlanmış bir İşlevsel Programlama Dilidir. Fonksiyonel programlama matematiksel fonksiyonlara dayanır. Haskell'in yanı sıra, İşlevsel Programlama paradigmasını takip eden diğer popüler dillerden bazıları şunlardır: Lisp, Python, Erlang, Racket, F #, Clojure, vb.

İçinde conventional programing, talimatlar belirli bir sözdiziminde veya formatta bir dizi bildirimler olarak alınır, ancak functional programingtüm hesaplama, ayrı matematiksel fonksiyonların bir kombinasyonu olarak kabul edilir.

Haskell ile Fonksiyonelleşmek

Haskell, yaygın olarak kullanılan tamamen işlevsel bir dildir. Burada, bu dili Java, C, C ++, PHP vb. Diğer geleneksel programlama dillerinden çok özel kılan birkaç noktayı listeledik.

  • Functional Language- Geleneksel programlama dilinde, derleyiciye, bilgisayarınıza "ne yapacağını" ve "nasıl yapacağını" söylemekten başka bir şey olmayan bir dizi görev veriyoruz. Ama Haskell'de bilgisayarımıza "ne olduğunu" söyleyeceğiz.

  • Laziness- Haskell tembel bir dildir. TarafındanlazyHaskell'in hiçbir ifadeyi sebepsiz yere değerlendirmeyeceğini kastediyoruz. Değerlendirme motoru bir ifadenin değerlendirilmesi gerektiğini tespit ettiğinde, bir ifade oluştururthunk data structure o özel değerlendirme için gerekli tüm bilgileri toplamak ve bunun için bir gösterge thunk data structure. Değerlendirme motoru, yalnızca söz konusu ifadenin değerlendirilmesi gerektiğinde çalışmaya başlayacaktır.

  • Modularity- Haskell uygulaması bir dizi işlevden başka bir şey değildir. Bir Haskell uygulamasının çok sayıda küçük Haskell uygulamasının bir koleksiyonu olduğunu söyleyebiliriz.

  • Statically Typed- Geleneksel programlama dilinde, türleriyle birlikte bir dizi değişken tanımlamamız gerekir. Buna karşılık Haskell, kesinlikle yazılmış bir dildir. Strictly Typed dili terimi ile Haskell derleyicisinin bildirilen değişkenin türünü anlayacak kadar akıllı olduğunu kastediyoruz, bu nedenle kullanılan değişkenin türünü açıkça belirtmemize gerek yok.

  • Maintainability - Haskell uygulamaları modülerdir ve bu nedenle bunların bakımı çok kolay ve uygun maliyetlidir.

Fonksiyonel programlar daha eşzamanlıdır ve daha doğru ve daha iyi performans sağlamak için uygulamada paralelliği takip ederler. Haskell bir istisna değildir; başa çıkacak şekilde geliştirildimultithreading etkili bir şekilde.

Selam Dünya

Haskell'in dinamizmini göstermek için basit bir örnek. Aşağıdaki koda bir göz atın. Tek ihtiyacımız olan, konsolda "Merhaba Word" yazdırmak için yalnızca bir satır.

main = putStrLn "Hello World"

Haskell derleyicisi yukarıdaki kod parçasıyla karşılaştığında, hemen aşağıdaki çıktıyı verir -

Hello World

Haskell'in gücünü ve sadeliğini göstermek için bu eğitim boyunca birçok örnek vereceğiz.

Haskell programlama ortamını çevrimiçi olarak şu adreste kurduk: https://www.tutorialspoint.com/compile_haskell_online.php

Bu çevrimiçi düzenleyici, Haskell programlama örneklerini uygulamak için birçok seçeneğe sahiptir. Sayfanın terminal bölümüne gidin ve yazın"ghci". Bu komut Haskell derleyicisini otomatik olarak yükler ve Haskell'i çevrimiçi olarak başlatır. Kullandıktan sonra aşağıdaki çıktıyı alacaksınızghci komut.

sh-4.3$ ghci
GHCi,version7.8.4:http://www.haskell.org/ghc/:?forhelp
Loading package ghc-prim...linking...done.
Loading packageinteger gmp...linking... done.
Loading package base...linking...done.
Prelude>

Haskell'i yerel sisteminizde çevrimdışı kullanmak istiyorsanız, mevcut Haskell kurulumunu resmi web sayfasından indirmeniz gerekir - https://www.haskell.org/downloads

Üç farklı tür vardır installers piyasada mevcut -

  • Minimal Installer - GHC (Glasgow Haskell Derleyicisi), CABAL (Bina Uygulamaları ve Kitaplıkları için Ortak Mimari) ve Yığın araçları sağlar.

  • Stack Installer- Bu yükleyicide GHC, yönetilen ücret zincirinin çapraz platformunda indirilebilir. Uygulamanızı, gerektiğinde API araçlarını güncelleyebilecek şekilde küresel olarak yükleyecektir. Haskell odaklı tüm bağımlılıkları otomatik olarak çözer.

  • Haskell Platform- Haskell'i kurmanın en iyi yolu budur çünkü tüm platformu makinenize ve bunu belirli bir yerden kuracaktır. Bu yükleyici, yukarıdaki iki yükleyici gibi dağıtılmaz.

Piyasada bulunan farklı yükleyici türlerini gördük, şimdi bu yükleyicileri makinemizde nasıl kullanacağımızı görelim. Bu eğitimde, Haskell derleyicisini sistemimize kurmak için Haskell platform yükleyicisini kullanacağız.

Windows'ta Ortam Kurulumu

Windows bilgisayarınızda Haskell ortamını kurmak için resmi web sitesine gidin https://www.haskell.org/platform/windows.html ve Yükleyiciyi özelleştirilebilir mimarinize göre indirin.

Sisteminizin mimarisine göz atın ve ilgili kurulum dosyasını indirin ve çalıştırın. Diğer Windows uygulamaları gibi yüklenecektir. Sisteminizin CABAL konfigürasyonunu güncellemeniz gerekebilir.

MAC'de Ortam Kurulumu

MAC sisteminizde Haskell ortamını kurmak için resmi web sitesine gidin https://www.haskell.org/platform/mac.html ve Mac yükleyiciyi indirin.

Linux'ta Ortam Kurulumu

Haskell'i Linux tabanlı bir sisteme kurmak, MAC ve Windows gibi o kadar da kolay olmayan bazı komutları çalıştırmayı gerektirir. Evet, yorucu ama güvenilir.

Haskell'i Linux sisteminize kurmak için aşağıdaki adımları takip edebilirsiniz -

Step 1 - Linux sisteminizde Haskell ortamını kurmak için resmi web sitesine gidin https://www.haskell.org/platform/linux.htmlve dağıtımınızı seçin. Tarayıcınızda aşağıdaki ekranı bulacaksınız.

Step 2- Dağıtımınızı seçin. Bizim durumumuzda Ubuntu kullanıyoruz. Bu seçeneği seçtikten sonra, Haskell'i yerel sistemimize kurma komutu ile ekranınızda aşağıdaki sayfayı alacaksınız.

Step 3 - Ctrl + Alt + T tuşlarına basarak bir terminal açın. Komutu çalıştırın "$ sudo apt-get install haskell-platform"ve Enter tuşuna basın. Kök parolanızla kimliğinizi doğruladıktan sonra sisteminize Haskell'i otomatik olarak indirmeye başlayacaktır. Kurduktan sonra bir onay mesajı alacaksınız.

Step 4- Terminalinize tekrar gidin ve GHCI komutunu çalıştırın. Prelude komut istemini aldığınızda Haskell'i yerel sisteminizde kullanmaya hazırsınız.

GHCI prologundan çıkmak için ": quit exit" komutunu kullanabilirsiniz.

Haskell tamamen işlevsel bir programlama dilidir, bu nedenle diğer programlama dillerinden çok daha etkileşimli ve akıllıdır. Bu bölümde, aslında önceden tanımlanmış veya bir şekilde akıllıca bilgisayar belleğine kodu çözülmüş Haskell'in temel veri modellerini öğreneceğiz.

Bu eğitim boyunca, web sitemizde bulunan Haskell çevrimiçi platformunu kullanacağız (https://www.tutorialspoint.com/codingground.htm).

Sayılar

Haskell, bazı sayıları bir sayı olarak çözecek kadar zekidir. Bu nedenle, diğer programlama dillerinde genellikle yaptığımız gibi, türünden harici olarak bahsetmenize gerek yoktur. Örnek olarak, prelude komut isteminize gidin ve sadece "2 + 2" yi çalıştırın ve enter tuşuna basın.

sh-4.3$ ghci 
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> 2+2

Sonuç olarak aşağıdaki çıktıyı alacaksınız.

4

Yukarıdaki kodda, GHCI derleyicisine, türlerini önceden tanımlamadan argüman olarak iki sayı ilettik, ancak derleyici bu iki girişi sayı olarak kolayca çözebilir.

Şimdi biraz daha karmaşık matematiksel hesaplamayı deneyelim ve akıllı derleyicimizin bize doğru çıktıyı verip vermediğini görelim. "15+ (5 * 5) -40" ile deneyin

Prelude> 15+(5*5)-40

Yukarıdaki ifade, beklenen çıktıya göre "0" verir.

0

Karakterler

Sayılar gibi, Haskell de kendisine girdi olarak verilen bir karakteri akıllıca tanımlayabilir. Haskell komut isteminize gidin ve çift veya tek tırnakla herhangi bir karakter yazın.

Aşağıdaki satırı girdi olarak verelim ve çıktısını kontrol edelim.

Prelude> :t "a"

Aşağıdaki çıktıyı üretecektir -

"a" :: [Char]

(:t) girişi sağlarken. Yukarıdaki örnekte,(:t)girdilerle ilgili belirli türü içermektir. İlerleyen bölümlerde bu tür hakkında daha fazla bilgi edineceğiz.

Bazı geçersiz girdileri karakter olarak geçirdiğimiz ve bu da bir hataya yol açtığımız aşağıdaki örneğe bir göz atın.

Prelude> :t a 
<interactive>:1:1: Not in scope: 'a'  

Prelude> a 
<interactive>:4:1: Not in scope: 'a'

"<interactive>: 4: 1: Kapsam dışı:" a '"hata mesajıyla Haskell derleyicisi, girişinizi tanıyamadığı konusunda bizi uyarıyor. Haskell, her şeyin bir sayı kullanılarak temsil edildiği bir dil türüdür.

Haskell, geleneksel ASCII kodlama stilini takip eder. Daha fazlasını anlamak için aşağıdaki örneğe bir göz atalım -

Prelude> '\97' 
'a'  
Prelude> '\67' 
'C'

Girişinizin ASCII formatına nasıl çözüldüğüne bakın.

Dize

Bir stringbir karakter koleksiyonundan başka bir şey değildir. Dizge kullanmak için belirli bir sözdizimi yoktur, ancak Haskell, bir dizeyi çift tırnakla temsil eden geleneksel stili izler.

"Tutorialspoint.com" dizesini geçtiğimiz aşağıdaki örneğe bir göz atın.

Prelude> :t "tutorialspoint.com"

Ekranda aşağıdaki çıktıyı üretecektir -

"tutorialspoint.com" :: [Char]

Tüm dizenin nasıl kodunun yalnızca bir Char dizisi olarak çözüldüğüne bakın. Diğer veri türüne ve sözdizimine geçelim. Gerçek uygulamamıza başladıktan sonra, tüm veri türlerine ve kullanımına alışmış olacağız.

Boole

Boolean veri türü de diğer veri türleri gibi oldukça basittir. "True" veya "False" gibi bazı Boolean girişlerini kullanarak farklı Boole işlemlerini kullanacağımız aşağıdaki örneğe bakın.

Prelude> True && True 
True  
Prelude> True && False 
False   
Prelude> True || True 
True  
Prelude> True || False 
True

Yukarıdaki örnekte, "True" ve "False" ın Boole değerleri olduğunu belirtmemize gerek yok. Haskell'in kendisi bunu çözebilir ve ilgili işlemleri yapabilir. Girdilerimizi "true" veya "false" ile değiştirelim.

Prelude> true

Aşağıdaki çıktıyı üretecektir -

<interactive>:9:1: Not in scope: 'true'

Yukarıdaki örnekte Haskell, "true" ile bir sayı değerini birbirinden ayıramadı, dolayısıyla bizim "true" girdimiz bir sayı değildir. Dolayısıyla, Haskell derleyicisi bizim girdimizin kapsamı olmadığını belirten bir hata atar.

Liste ve Liste Anlama

Diğer veri türleri gibi, Listayrıca Haskell'de kullanılan çok kullanışlı bir veri türüdür. Örneğin, [a, b, c] bir karakter listesidir, dolayısıyla tanım gereği Liste, virgülle ayrılmış aynı veri türünün bir koleksiyonudur.

Diğer veri türleri gibi, bir Listeyi Liste olarak bildirmeniz gerekmez. Haskell, ifadede kullanılan sözdizimine bakarak girişinizin kodunu çözecek kadar akıllıdır.

Haskell'in Listeyi nasıl ele aldığını gösteren aşağıdaki örneğe bir göz atın.

Prelude> [1,2,3,4,5]

Aşağıdaki çıktıyı üretecektir -

[1,2,3,4,5]

Haskell'deki listeler, doğası gereği homojendir, yani farklı türden bir veri türü listesi bildirmenize izin vermezler. [1,2,3,4,5, a, b, c, d, e, f] gibi herhangi bir liste bir hata üretecektir.

Prelude> [1,2,3,4,5,a,b,c,d,e,f]

Bu kod aşağıdaki hatayı üretecektir -

<interactive>:17:12: Not in scope: 'a' 
<interactive>:17:14: Not in scope: 'b' 
<interactive>:17:16: Not in scope: 'c' 
<interactive>:17:18: Not in scope: 'd' 
<interactive>:17:20: Not in scope: 'e' 
<interactive>:17:22: Not in scope: 'f'

Liste Anlama

Liste anlama, matematiksel ifadeyi kullanarak bir liste oluşturma sürecidir. [Çıktı | biçiminde matematiksel ifade kullanarak bir liste oluşturduğumuz aşağıdaki örneğe bakın. aralık, koşul].

Prelude> [x*2| x<-[1..10]] 
[2,4,6,8,10,12,14,16,18,20]  
Prelude> [x*2| x<-[1..5]] 
[2,4,6,8,10]  
Prelude> [x| x<-[1..5]] 
[1,2,3,4,5]

Matematiksel ifadeyi kullanarak bir Liste oluşturmanın bu yöntemi şu şekilde adlandırılır: List Comprehension.

Tuple

Haskell, tek bir veri türünde birden çok değeri bildirmenin başka bir yolunu sağlar. Olarak bilinirTuple. Bir Tuple, bir Liste olarak düşünülebilir, ancak bir Tuple ve bir Liste arasında bazı teknik farklılıklar vardır.

Bir Tuple, çalışma zamanında öğelerin sayısını değiştiremediğimiz için değişmez bir veri türüdür, oysa Liste değiştirilebilir bir veri türüdür.

Öte yandan, Liste homojen bir veri türüdür, ancak Tuple doğası gereği heterojendir, çünkü bir Tuple içinde farklı türde veriler içerebilir.

Tuple'lar tek parantez ile temsil edilir. Haskell'in bir Tuple'a nasıl davrandığını görmek için aşağıdaki örneğe bir göz atın.

Prelude> (1,1,'a')

Aşağıdaki çıktıyı üretecektir -

(1,1,'a')

Yukarıdaki örnekte, iki ile bir Tuple kullandık number tür değişkenleri ve a char tip değişken.

Bu bölümde Haskell'de kullanılan farklı operatörler hakkında bilgi edineceğiz. Diğer programlama dilleri gibi Haskell de toplama, çıkarma, çarpma, vb. Gibi bazı temel işlemleri akıllıca gerçekleştirir. Sonraki bölümlerde, farklı operatörler ve bunların kullanımı hakkında daha fazla şey öğreneceğiz.

Bu bölümde, çevrimiçi platformumuzu kullanarak Haskell'de farklı operatörler kullanacağız (https://www.tutorialspoint.com/codingground.htm). Sadece kullandığımızı hatırlainteger sayıları yazın çünkü daha fazlasını öğreneceğiz decimal sonraki bölümlere sayıları yazın.

Toplama Operatörü

Adından da anlaşılacağı gibi, toplama (+) operatörü toplama işlevi için kullanılır. Aşağıdaki örnek kod, Haskell'de nasıl iki tamsayı ekleyebileceğinizi gösterir -

main = do 
   let var1 = 2 
   let var2 = 3 
   putStrLn "The addition of the two numbers is:" 
   print(var1 + var2)

Yukarıdaki dosyada iki ayrı değişken oluşturduk var1 ve var2. Sonunda, sonucu kullanarakadditionŞebeke. Kullancompile ve execute Kodunuzu çalıştırmak için düğmeye basın.

Bu kod, ekranda aşağıdaki çıktıyı üretecektir -

The addition of the two numbers is:
5

Çıkarma Operatörü

Adından da anlaşılacağı gibi, bu operatör çıkarma işlemi için kullanılır. Aşağıdaki örnek kod, Haskell'de iki tamsayıyı nasıl çıkarabileceğinizi gösterir -

main = do 
   let var1 = 10 
   let var2 = 6 
   putStrLn "The Subtraction of the two numbers is:" 
   print(var1 - var2)

Bu örnekte, iki değişken oluşturduk var1 ve var2. Bundan sonra, iki değeri çıkarmak için çıkarma (-) operatörünü kullanırız.

Bu kod, ekranda aşağıdaki çıktıyı üretecektir -

The Subtraction of the two numbers is:
4

Çarpma Operatörü

Bu operatör, çarpma işlemleri için kullanılır. Aşağıdaki kod, Haskell'de Çarpma Operatörü kullanılarak iki sayının nasıl çarpılacağını gösterir -

main = do 
   let var1 = 2 
   let var2 = 3 
   putStrLn "The Multiplication of the Two Numbers is:" 
   print(var1 * var2)

Bu kod, çevrimiçi platformumuzda çalıştırdığınızda aşağıdaki çıktıyı üretecektir -

The Multiplication of the Two Numbers is:
6

Bölüm Operatörü

Aşağıdaki koda bir göz atın. Haskell'de iki sayıyı nasıl bölebileceğinizi gösterir -

main = do 
   let var1 = 12 
   let var2 = 3 
   putStrLn "The Division of the Two Numbers is:" 
   print(var1/var2)

Aşağıdaki çıktıyı üretecektir -

The Division of the Two Numbers is: 
4.0

Sıra / Aralık Operatörü

Sıra veya Aralık, Haskell'de özel bir operatördür. "(..)" ile gösterilir. Bu operatörü, bir dizi değer içeren bir listeyi bildirirken kullanabilirsiniz.

1'den 10'a kadar tüm değerleri yazdırmak istiyorsanız, "[1..10]" gibi bir şey kullanabilirsiniz. Benzer şekilde, "a" dan "z" ye tüm alfabeleri oluşturmak istiyorsanız, o zaman sadece yazabilirsiniz"[a..z]".

Aşağıdaki kod, 1'den 10'a kadar tüm değerleri yazdırmak için Sıra işlecini nasıl kullanabileceğinizi gösterir -

main :: IO() 
main = do 
   print [1..10]

Aşağıdaki çıktıyı üretecektir -

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

Karar Verme, programcıların kod akışında bir koşul uygulamasına izin veren bir özelliktir. Programcı, önceden tanımlanmış bir koşula bağlı olarak bir dizi talimat yürütebilir. Aşağıdaki akış şeması Haskell'in karar verme yapısını göstermektedir -

Haskell, aşağıdaki türden karar verme beyanları sağlar:

Sr.No. Açıklama ve Açıklama
1 if – else ifadesi

Bir if ile ifade elseBeyan. Talimatelse blok yalnızca verilen Boolean koşulu karşılanamadığında çalışacaktır.

2 İç içe geçmiş if-else ifadesi

Çoklu if ardından gelen bloklar else bloklar

Haskell işlevsel bir dildir ve kesinlikle yazılmıştır, bu da tüm uygulamada kullanılan veri türünün derleyici tarafından derleme zamanında bilineceği anlamına gelir.

Dahili Tip Sınıfı

Haskell'de her ifade matematiksel bir ifade olarak kabul edilir ve bu ifadenin kategorisine bir Type. Derleme zamanında kullanılan ifadenin veri türü olarak "Tür" diyebilirsiniz.

Hakkında daha fazla bilgi edinmek için Type": t" komutunu kullanacağız. Genel bir şekilde,Type bir değer olarak düşünülebilir, oysa Type Classbenzer türden bir dizi olarak düşünülebilir. Bu bölümde, farklı Dahili Tipler hakkında bilgi edineceğiz.

Int

IntTamsayı türleri verilerini temsil eden bir tür sınıfıdır. 2147483647 ile -2147483647 aralığındaki her tam sayı,Inttype sınıfı. Aşağıdaki örnekte, işlevfType() tanımlanan türüne göre davranacaktır.

fType :: Int -> Int -> Int 
fType x y = x*x + y*y
main = print (fType 2 4)

Burada fonksiyonun türünü belirledik fType() gibi int. Fonksiyon iki alırint değerler ve bir döndürür intdeğer. Bu kod parçasını derler ve yürütürseniz, aşağıdaki çıktıyı üretir -

sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts 
sh-4.3$ main
20

Tamsayı

Integer üst kümesi olarak düşünülebilir Int. Bu değer herhangi bir sayı ile sınırlı değildir, dolayısıyla bir Tamsayı herhangi bir sınırlama olmaksızın herhangi bir uzunlukta olabilir. Arasındaki temel farkı görmek içinInt ve Integer türler, yukarıdaki kodu aşağıdaki gibi değiştirelim -

fType :: Int -> Int -> Int 
fType x y = x*x + y*y 
main = print (fType 212124454 44545454454554545445454544545)

Yukarıdaki kod parçasını derlerseniz, aşağıdaki hata mesajı atılacaktır -

main.hs:3:31: Warning:            
   Literal 44545454454554545445454544545 is out of the Int range -
   9223372036854775808..9223372036854775807 
Linking main ...

Bu hata, fType () fonksiyonumuzun bir Int tipi değer beklemesi ve bazı gerçek büyük Int tipi değeri iletmemiz nedeniyle oluştu. Bu hatayı önlemek için, "Int" türünü "Tamsayı" ile değiştirelim ve farkı gözlemleyelim.

fType :: Integer -> Integer -> Integer 
fType x y = x*x + y*y 
main = print (fType 212124454 4454545445455454545445445454544545)

Şimdi, aşağıdaki çıktıyı üretecek -

sh-4.3$ main
1984297512562793395882644631364297686099210302577374055141

Yüzer

Aşağıdaki kod parçasına bir göz atın. Haskell'de Float türünün nasıl çalıştığını gösterir -

fType :: Float -> Float -> Float 
fType x y = x*x + y*y 
main = print (fType 2.5 3.8)

Fonksiyon, girdi olarak iki float değeri alır ve çıktı olarak başka bir float değeri verir. Bu kodu derleyip yürüttüğünüzde, aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
20.689999

Çift

Doublesonunda çift duyarlıklı bir kayan nokta numarasıdır. Aşağıdaki örneğe bir göz atın -

fType :: Double -> Double -> Double 
fType x y = x*x + y*y 
main = print (fType 2.56 3.81)

Yukarıdaki kod parçasını çalıştırdığınızda, aşağıdaki çıktıyı üretecektir -

sh-4.3$ main 
21.0697

Bool

Boolbir Boole Türüdür. Doğru veya Yanlış olabilir. Bool türünün Haskell'de nasıl çalıştığını anlamak için aşağıdaki kodu çalıştırın -

main = do  
   let x = True 
   
   if x == False 
      then putStrLn "X matches with Bool Type" 
   else putStrLn "X is not a Bool Type"

Burada, bir "x" değişkenini bir Bool olarak tanımlıyor ve orijinalliğini kontrol etmek için onu başka bir Boolean değeriyle karşılaştırıyoruz. Aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
X is not a Bool Type

Char

Karakterler, Karakterleri temsil eder. Tek bir alıntı içindeki her şey bir Karakter olarak kabul edilir. Aşağıdaki kodda, öncekifType() Char değerini kabul etmek ve Char değerini çıktı olarak döndürmek için işlev.

fType :: Char-> Char 
fType x = 'K' 
main = do  
   let x = 'v' 
   print (fType x)

Yukarıdaki kod parçası arayacak fType() ile işlev char'v' değeri ancak başka bir karakter değeri, yani 'K' döndürür. İşte çıktısı -

sh-4.3$ main 
'K'

Bu türleri açıkça kullanmayacağımızı unutmayın çünkü Haskell, türü bildirilmeden önce yakalayacak kadar zeki. Bu eğitimin sonraki bölümlerinde, farklı türlerin ve Tür sınıflarının Haskell'i nasıl güçlü bir şekilde yazılmış bir dil yaptığını göreceğiz.

EQ Tipi Sınıfı

EQtür sınıfı, bir ifadenin eşitliğini test etmek için işlevsellik sağlayan bir arabirimdir. Bir ifadenin eşitliğini kontrol etmek isteyen herhangi bir Type sınıfı, bu EQ Type Class'ın bir parçası olmalıdır.

Yukarıda belirtilen tüm standart Tip sınıfları bunun bir parçasıdır EQsınıf. Yukarıda bahsedilen türlerden herhangi birini kullanarak herhangi bir eşitliği kontrol ettiğimizde, aslında bir çağrı yapıyoruzEQ type sınıfı.

Aşağıdaki örnekte, kullanıyoruz EQ "==" veya "/ =" işlemini kullanarak dahili olarak yazın.

main = do 
   if 8 /= 8 
      then putStrLn "The values are Equal" 
   else putStrLn "The values are not Equal"

Aşağıdaki çıktıyı verecektir -

sh-4.3$ main 
The values are not Equal

Ord Tipi Sınıf

Ordbize siparişin işlevselliğini veren başka bir arayüz sınıfıdır. Hepsitypes Şimdiye kadar kullandığımız, bunun bir parçası Ordarayüz. EQ arayüzü gibi, Ord arayüzü ">", "<", "<=", "> =", "karşılaştırma" kullanılarak çağrılabilir.

Lütfen bu Tip Sınıfının "karşılaştırma" işlevini kullandığımız aşağıdaki örneği bulun.

main = print (4 <= 2)

Burada Haskell derleyicisi 4'ün 2'den küçük veya 2'ye eşit olup olmadığını kontrol edecektir. Öyle olmadığı için kod aşağıdaki çıktıyı üretecektir -

sh-4.3$ main 
False

Göstermek

Showargümanını String olarak basma işlevine sahiptir. Argümanı ne olursa olsun, sonucu daima bir String olarak yazdırır. Aşağıdaki örnekte, bu arayüzü kullanarak tüm listeyi yazdıracağız. Bu arayüzü çağırmak için "show" kullanılabilir.

main = print (show [1..10])

Konsolda aşağıdaki çıktıyı üretecektir. Buradaki çift tırnak, bunun String tipi bir değer olduğunu gösterir.

sh-4.3$ main 
"[1,2,3,4,5,6,7,8,9,10]"

Okuyun

Readinterface, Show ile aynı şeyi yapar, ancak sonucu String formatında yazdırmaz. Aşağıdaki kodda,read bir dize değerini okumak ve aynısını bir Int değerine dönüştürmek için arabirim.

main = print (readInt "12") 
readInt :: String -> Int 
readInt = read

Burada, bir String değişkenini ("12") readIntdönüşümden sonra 12 (bir Int değeri) döndüren yöntem. İşte çıktısı -

sh-4.3$ main 
12

Sıralama

EnumHaskell'de sıralı veya sıralı işlevselliği etkinleştiren başka bir Tür sınıfı türüdür. Bu Type sınıfına aşağıdaki gibi komutlarla erişilebilir:Succ, Pred, Bool, Char, vb.

Aşağıdaki kod, 12'nin ardıl değerinin nasıl bulunacağını gösterir.

main = print (succ 12)

Aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
13

Sınırlı

Üst ve alt sınırları olan tüm türler bu Tip Sınıfı kapsamındadır. Örneğin,Int tür verilerinin maksimum sınırı "9223372036854775807" ve minimum sınırı "-9223372036854775808".

Aşağıdaki kod, Haskell'in Int türünün maksimum ve minimum sınırını nasıl belirlediğini gösterir.

main = do 
   print (maxBound :: Int) 
   print (minBound :: Int)

Aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
9223372036854775807
-9223372036854775808

Şimdi, Char, Float ve Bool türlerinin maksimum ve minimum sınırını bulmaya çalışın.

Num

Bu tür sınıfı, sayısal işlemler için kullanılır. Int, Integer, Float ve Double gibi türler bu Type sınıfına girer. Aşağıdaki koda bir göz atın -

main = do 
   print(2 :: Int)  
   print(2 :: Float)

Aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
2
2.0

İntegral

IntegralNum Type Class'ın bir alt sınıfı olarak düşünülebilir. Num Type sınıfı tüm sayı türlerini tutarken Integral türü sınıfı yalnızca integral sayılar için kullanılır. Int ve Integer, bu Type sınıfının altındaki türlerdir.

Yüzer

Integral gibi Floating da Num Type sınıfının bir parçasıdır, ancak yalnızca kayan noktalı sayıları tutar. DolayısıylaFloat ve Double bu tip sınıfa gelin.

Özel Tip Sınıfı

Diğer herhangi bir programlama dili gibi Haskell, geliştiricilerin kullanıcı tanımlı türleri tanımlamasına izin verir. Aşağıdaki örnekte, kullanıcı tanımlı bir tip oluşturup kullanacağız.

data Area = Circle Float Float Float  
surface :: Area -> Float   
surface (Circle _ _ r) = pi * r ^ 2   
main = print (surface $ Circle 10 20 10 )

Burada yeni bir tür oluşturduk. Area. Sonra, bir dairenin alanını hesaplamak için bu türü kullanıyoruz. Yukarıdaki örnekte, "yüzey", alanArea girdi olarak ve üretir Float çıktı olarak.

"Veri" nin burada bir anahtar kelime olduğunu ve Haskell'deki tüm kullanıcı tanımlı türlerin her zaman büyük harfle başladığını unutmayın.

Aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
314.15927

Fonksiyonlar, işlevsel bir programlama dili olduğu için Haskell'de önemli bir rol oynar. Diğer diller gibi Haskell'in de kendi işlevsel tanımı ve beyanı vardır.

  • İşlev bildirimi, işlev adı ve çıktısı ile birlikte argüman listesinden oluşur.

  • İşlev tanımı, aslında bir işlevi tanımladığınız yerdir.

Küçük bir örnek alalım add bu kavramı ayrıntılı olarak anlama işlevi.

add :: Integer -> Integer -> Integer   --function declaration 
add x y =  x + y                       --function definition 

main = do 
   putStrLn "The addition of the two numbers is:"  
   print(add 2 5)    --calling a function

Burada fonksiyonumuzu ilk satırda ve ikinci satırda ilan ettik, iki argüman alacak ve bir tamsayı türü çıktı üretecek gerçek fonksiyonumuzu yazdık.

Diğer dillerin çoğu gibi Haskell de kodu mainyöntem. Kodumuz aşağıdaki çıktıyı üretecektir -

The addition of the two numbers is:
7

Desen Eşleştirme

Desen Eşleştirme, belirli türdeki ifadeleri eşleştirme işlemidir. Kodunuzu basitleştirmek için bir teknikten başka bir şey değildir. Bu teknik, herhangi bir Type sınıfına uygulanabilir. If-Else, alternatif bir desen eşleştirme seçeneği olarak kullanılabilir.

Örüntü Eşleştirme, çalışma zamanında, bağımsız değişken listesine bağlı olarak farklı yöntemlerin yürütülebildiği dinamik polimorfizmin bir çeşidi olarak düşünülebilir.

Aşağıdaki kod bloğuna bir göz atın. Burada, bir sayının faktöriyelini hesaplamak için Örüntü Eşleştirme tekniğini kullandık.

fact :: Int -> Int 
fact 0 = 1 
fact n = n * fact ( n - 1 ) 

main = do 
   putStrLn "The factorial of 5 is:" 
   print (fact 5)

Hepimiz bir sayının faktöriyelini nasıl hesaplayacağımızı biliyoruz. Derleyici, bir bağımsız değişkenle "olgu" adlı bir işlevi aramaya başlayacaktır. Eğer argüman 0'a eşit değilse, sayı gerçek argümandan 1 daha küçük olan aynı işlevi çağırmaya devam edecektir.

Argümanın modeli 0 ile tam olarak eşleştiğinde, bizim kalıbımızı "olgu 0 = 1" olarak çağıracaktır. Kodumuz aşağıdaki çıktıyı üretecektir -

The factorial of 5 is:
120

Muhafızlar

Guardsdesen eşleştirmeye çok benzeyen bir kavramdır. Desen eşleştirmede genellikle bir veya daha fazla ifadeyle eşleşiriz, ancakguards bir ifadenin bazı özelliklerini test etmek için.

Örüntü eşleştirmenin kullanılması tavsiye edilse de guardsancak bir geliştiricinin bakış açısından, guardsdaha okunaklı ve basittir. İlk kez kullananlar için,guards If-Else ifadelerine çok benzer görünebilir, ancak işlevsel olarak farklıdırlar.

Aşağıdaki kodda, factorial kavramını kullanarak programı guards.

fact :: Integer -> Integer 
fact n | n == 0 = 1 
       | n /= 0 = n * fact (n-1) 
main = do 
   putStrLn "The factorial of 5 is:"  
   print (fact 5)

Burada iki ilan ettik guards"|" ile ayrılmış ve çağırmakfact işlevi main. Dahili olarak, aşağıdaki çıktıyı vermek için derleyici desen eşleştirme durumunda olduğu gibi aynı şekilde çalışacaktır -

The factorial of 5 is:
120

Madde nerede

Whereistenen bir çıktıyı oluşturmak için çalışma zamanında kullanılabilen bir anahtar sözcük veya dahili işlevdir. İşlev hesaplaması karmaşık hale geldiğinde çok yardımcı olabilir.

Girişinizin birden çok parametresi olan karmaşık bir ifade olduğu bir senaryo düşünün. Bu gibi durumlarda, "where" cümlesini kullanarak tüm ifadeyi küçük parçalara ayırabilirsiniz.

Aşağıdaki örnekte, karmaşık bir matematiksel ifade alıyoruz. Haskell'i kullanarak bir polinom denkleminin [x ^ 2 - 8x + 6] köklerini nasıl bulabileceğinizi göstereceğiz.

roots :: (Float, Float, Float) -> (Float, Float)  
roots (a,b,c) = (x1, x2) where 
   x1 = e + sqrt d / (2 * a) 
   x2 = e - sqrt d / (2 * a) 
   d = b * b - 4 * a * c  
   e = - b / (2 * a)  
main = do 
   putStrLn "The roots of our Polynomial equation are:" 
   print (roots(1,-8,6))

Verilen polinom fonksiyonunun köklerini hesaplamak için ifademizin karmaşıklığına dikkat edin. Oldukça karmaşık. Bu nedenle, ifadeyi kullanarakwherefıkra. Yukarıdaki kod parçası aşağıdaki çıktıyı üretecektir -

The roots of our Polynomial equation are:
(7.1622777,0.8377223)

Özyineleme İşlevi

Özyineleme, bir işlevin kendisini tekrar tekrar çağırdığı bir durumdur. Haskell, herhangi bir ifadeyi birden fazla döngüde kullanma olanağı sağlamaz. Bunun yerine Haskell, tüm işlevselliğinizi farklı işlevler koleksiyonuna ayırmanızı ve işlevselliğinizi uygulamak için özyineleme tekniğini kullanmanızı ister.

Bir sayının faktöriyelini hesapladığımız kalıp eşleştirme örneğimizi tekrar ele alalım. Bir sayının faktöriyelini bulmak, Özyinelemeyi kullanmanın klasik bir örneğidir. Burada, "Desen eşlemesinin özyinelemeden farkı nedir?" Bu ikisi arasındaki fark, kullanılma şekillerinde yatmaktadır.Örüntü eşleme, terminal sınırlamasını ayarlamakta çalışır, oysa özyineleme bir işlev çağrısıdır.

Aşağıdaki örnekte, 5'in faktöriyelini hesaplamak için hem örüntü eşleştirmeyi hem de özyinelemeyi kullandık.

fact :: Int -> Int 
fact 0 = 1 
fact n = n * fact ( n - 1 ) 

main = do 
   putStrLn "The factorial of 5 is:" 
   print (fact 5)

Aşağıdaki çıktıyı üretecektir -

The factorial of 5 is:
120

Yüksek Sipariş İşlevi

Şimdiye kadar Haskell fonksiyonlarının bir tane aldığını gördük. type girdi olarak ve başka bir şey üret typediğer zorunlu dillerde oldukça benzer olan çıktı olarak. Yüksek Sıralı İşlevler, bir işlevi girdi veya çıktı bağımsız değişkeni olarak kullanabileceğiniz Haskell'in benzersiz bir özelliğidir.

Sanal bir kavram olmasına rağmen, gerçek dünya programlarında Haskell'de tanımladığımız her işlev, çıktı sağlamak için üst düzey mekanizma kullanır. Haskell'in kütüphane fonksiyonuna bakma şansınız olursa, kütüphane fonksiyonlarının çoğunun daha yüksek sırayla yazıldığını göreceksiniz.

Yerleşik bir üst düzey fonksiyon haritasını içe aktaracağımız ve seçimimize göre başka bir yüksek dereceli işlevi uygulamak için aynısını kullanacağımız bir örnek alalım.

import Data.Char  
import Prelude hiding (map) 

map :: (a -> b) -> [a] -> [b] 
map _ [] = [] 
map func (x : abc) = func x : map func abc  
main = print $ map toUpper "tutorialspoint.com"

Yukarıdaki örnekte, toUpper Tip Sınıfının işlevi Chargirdimizi büyük harfe dönüştürmek için. Burada, "harita" yöntemi, bir işlevi argüman olarak alıyor ve gerekli çıktıyı döndürüyor. İşte çıktısı -

sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts sh-4.3$ main
"TUTORIALSPOINT.COM"

Lambda İfadesi

Bazen bir uygulamanın tüm ömrü boyunca yalnızca bir kez kullanılacak bir işlev yazmamız gerekir. Bu tür durumlarla başa çıkmak için Haskell geliştiricileri,lambda expression veya lambda function.

Tanımı olmayan bir işleve lambda işlevi denir. Bir lambda işlevi "\" karakteriyle gösterilir. Herhangi bir fonksiyon oluşturmadan girdi değerini 1 artıracağımız aşağıdaki örneği alalım.

main = do 
   putStrLn "The successor of 4 is:"  
   print ((\x -> x + 1) 4)

Burada adı olmayan anonim bir işlev oluşturduk. 4 tamsayısını bağımsız değişken olarak alır ve çıktı değerini yazdırır. Temelde, düzgün bir şekilde bildirmeden bir işlevi çalıştırıyoruz. Lambda ifadelerinin güzelliği budur.

Lambda ifademiz aşağıdaki çıktıyı üretecektir -

sh-4.3$ main
The successor of 4 is:
5

Şimdiye kadar, birçok Haskell işlevi türünü tartıştık ve bu işlevleri çağırmak için farklı yollar kullandık. Bu bölümde, herhangi bir özel Type sınıfını içe aktarmadan Haskell'de kolayca kullanılabilecek bazı temel işlevleri öğreneceğiz. Bu işlevlerin çoğu, diğer üst düzey işlevlerin bir parçasıdır.

Head Function

Head function works on a List. It returns the first of the input argument which is basically a list. In the following example, we are passing a list with 10 values and we are generating the first element of that list using the head function.

main = do 
   let x = [1..10]   
   putStrLn "Our list is:"  
   print (x) 
   putStrLn "The first element of the list is:" 
   print (head x)

It will produce the following output −

Our list is: 
[1,2,3,4,5,6,7,8,9,10]
The first element of the list is:
1

Tail Function

Tail is the function that complements the head function. It takes a list as the input and yields the entire list without the head part. That means, the tail function returns the entire list without the first element. Take a look at the following example −

main = do 
   let x = [1..10]   
   putStrLn "Our list is:"  
   print (x) 
   putStrLn "The tail of our list is:" 
   print (tail x)

It will produce the following output −

Our list is:
[1,2,3,4,5,6,7,8,9,10]
The tail of our list is:
[2,3,4,5,6,7,8,9,10]

Last Function

As the name suggests, it yields the last element of the list that is provided as the input. Check the following example.

main = do 
   let x = [1..10]   
   putStrLn "Our list is:"  
   print (x) 
   putStrLn "The last element of our list is:" 
   print (last x)

It will produce the following output −

Our list is:
[1,2,3,4,5,6,7,8,9,10]
The last element of our list is:
10

Init Function

Init works exactly as the opposite of tail function. It takes a list as an argument and returns the entire list without the last entry.

main = do 
   let x = [1..10]   
   putStrLn "Our list is:"  
   print (x) 
   putStrLn "Our list without the last entry:"  
   print (init x)

Now, observe its output −

Our list is:
[1,2,3,4,5,6,7,8,9,10]
Our list without the last entry:
[1,2,3,4,5,6,7,8,9]

Null Function

Null is a Boolean check function which works on a String and returns True only when the given list is empty, otherwise it returns False. The following code checks whether the supplied list is empty or not.

main = do 
   let x = [1..10]   
   putStrLn "Our list is:"  
   print (x) 
   putStrLn "Is our list empty?"  
   print (null x)

It will produce the following output −

Our list is:
[1,2,3,4,5,6,7,8,9,10]
Is our list empty?
False

Reverse Function

It works on a String input and converts the entire input into reverse order and give one output as a result. Below is the code base for this function.

main = do 
   let x = [1..10]  
   putStrLn "Our list is:" 
   print (x) 
   putStrLn "The list in Reverse Order is:" 
   print (reverse x)

It will produce the following output −

Our list is:
[1,2,3,4,5,6,7,8,9,10]
The list in Reverse Order is:
[10,9,8,7,6,5,4,3,2,1]

Length Function

This function is used to calculate the length of the list given as an argument. Take a look at the following example −

main = do 
   let x = [1..10]   
   putStrLn "Our list is:" 
   print (x) 
   putStrLn "The length of this list is:" 
   print (length x)

We have 10 elements in our list, hence our code will yield 10 as the output.

Our list is:
[1,2,3,4,5,6,7,8,9,10]
The length of this list is:
10

Take Function

Take function is used to create a sub-string from another String. The following code shows how you can use the take function in Haskell −

main = print(take 5 ([1 .. 10]))

The code generates a sub-string containing 5 elements from the supplied list −

[1,2,3,4,5]

Drop Function

This function is also used to generate a sub-string. It functions as the opposite of the take function. Look at the following piece of code −

main = print(drop 5 ([1 .. 10]))

The code drops the first 5 elements from the supplied list and prints the remaining 5 elements. It will produce the following output −

[6,7,8,9,10]

Maximum Function

This function is used to find the element with the maximum value from the supplied list. Let us see how to use it in practice −

main = do 
   let x = [1,45,565,1245,02,2]   
   putStrLn "The maximum value element of the list is:"  
   print (maximum x)

The above piece of code will generate following output −

The maximum value element of the list is:
1245

Minimum Function

This function is used to find the element with the minimum value from the supplied list. It’s just the opposite of the maximum function.

main = do 
   let x = [1,45,565,1245,02,2]   
   putStrLn "The minimum value element of the list is:"  
   print (minimum x)

The output of the above code is −

The minimum value element of the list is:
1

Sum Function

As the name suggests, this function returns the summation of all the elements present in the supplied list. The following code takes a list of 5 elements and returns their summation as the output.

main = do 
   let x = [1..5] 
   putStrLn "Our list is:" 
   print (x) 
   putStrLn "The summation of the list elements is:" 
   print (sum x)

It will produce the following output −

Our list is:
[1,2,3,4,5]
The summation of the list elements is:
15

Product Function

You can use this function to multiply all the elements in a list and print its value.

main = do 
   let x = [1..5] 
   putStrLn "Our list is:" 
   print (x) 
   putStrLn "The multiplication of the list elements is:" 
   print (product x)

Our code will produce the following output −

Our list is:
[1,2,3,4,5]
The multiplication of the list elements is: 
120

Elem Function

This function is used to check whether the supplied list contains a specific element or not. Accordingly, it either returns a true or a false.

The following code checks whether the supplied list of elements contains the value 786.

main = do 
   let x = [1,45,155,1785] 
   putStrLn "Our list is:" 
   print (x) 
   putStrLn "Does it contain 786?" 
   print (elem 786 (x))

It will produce the following output −

Our list is:
[1,45,155,1785]
Does it contain 786?
False

Use the same code to check if the supplied list contains the value 1785 or not.

Function Composition is the process of using the output of one function as an input of another function. It will be better if we learn the mathematics behind composition. In mathematics, composition is denoted by f{g(x)} where g() is a function and its output in used as an input of another function, that is, f().

Function composition can be implemented using any two functions, provided the output type of one function matches with the input type of the second function. We use the dot operator (.) to implement function composition in Haskell.

Take a look at the following example code. Here, we have used function composition to calculate whether an input number is even or odd.

eveno :: Int -> Bool 
noto  :: Bool -> String 

eveno x = if x `rem` 2 == 0 
   then True 
else False 
noto x = if x == True 
   then "This is an even Number" 
else "This is an ODD number" 

main = do 
   putStrLn "Example of Haskell Function composition" 
   print ((noto.eveno)(16))

Burada, main fonksiyon, iki fonksiyon diyoruz, noto ve eveno, eşzamanlı. Derleyici önce işlevi çağıracaktır"eveno()" ile 16bir argüman olarak. Bundan sonra derleyici,eveno girdi olarak yöntem noto() yöntem.

Çıktısı aşağıdaki gibi olacaktır -

Example of Haskell Function composition                
"This is an even Number"

16 sayısını girdi olarak (çift sayıdır) sağladığımız için, eveno() fonksiyon döner trueiçin girdi haline gelen noto() işlevi ve şu çıktıyı döndürür: "Bu bir çift Sayıdır".

Java üzerinde çalıştıysanız, tüm sınıfların nasıl bir klasöre bağlandığını bilirsiniz. package. Benzer şekilde, Haskell bir koleksiyon olarak düşünülebilirmodules.

Haskell işlevsel bir dildir ve her şey bir ifade olarak belirtilir, bu nedenle bir Modül benzer veya ilgili işlev türlerinin bir koleksiyonu olarak adlandırılabilir.

Yapabilirsin importbir modülden başka bir modüle bir işlev. Diğer işlevleri tanımlamaya başlamadan önce tüm "içe aktarma" ifadeleri önce gelmelidir. Bu bölümde Haskell modüllerinin farklı özelliklerini öğreneceğiz.

Liste Modülü

List çalışmak için bazı harika işlevler sağlar listveri yazın. Liste modülünü içe aktardıktan sonra, emrinizde çok çeşitli işlevlere sahip olursunuz.

Aşağıdaki örnekte, Liste modülünün altında bulunan bazı önemli işlevleri kullandık.

import Data.List  

main = do  
   putStrLn("Different methods of List Module") 
   print(intersperse '.' "Tutorialspoint.com") 
   print(intercalate " " ["Lets","Start","with","Haskell"]) 
   print(splitAt 7 "HaskellTutorial") 
   print (sort [8,5,3,2,1,6,4,2])

Burada, onları tanımlamadan bile birçok fonksiyonumuz var. Bunun nedeni, bu işlevlerin Liste modülünde mevcut olmasıdır. List modülünü içe aktardıktan sonra, Haskell derleyicisi tüm bu işlevleri genel ad alanında kullanılabilir hale getirdi. Dolayısıyla bu işlevleri kullanabiliriz.

Kodumuz aşağıdaki çıktıyı verecektir -

Different methods of List Module
"T.u.t.o.r.i.a.l.s.p.o.i.n.t...c.o.m"
"Lets Start with Haskell"
("Haskell","Tutorial")
[1,2,2,3,4,5,6,8]

Char Modülü

Charmodül, Karakter tipiyle çalışmak için önceden tanımlanmış birçok işleve sahiptir. Aşağıdaki kod bloğuna bir göz atın -

import Data.Char 

main = do  
   putStrLn("Different methods of Char Module") 
   print(toUpper 'a') 
   print(words "Let us study tonight") 
   print(toLower 'A')

İşte fonksiyonlar toUpper ve toLower zaten içinde tanımlanmıştır Charmodül. Aşağıdaki çıktıyı üretecektir -

Different methods of Char Module
'A'
["Let","us","study","tonight"]
'a'

Harita Modülü

Mapsıralanmamış katma değerli çift tipi bir veri türüdür. Birçok kullanışlı fonksiyona sahip yaygın olarak kullanılan bir modüldür. Aşağıdaki örnek, Harita modülünde bulunan önceden tanımlanmış bir işlevi nasıl kullanabileceğinizi gösterir.

import Data.Map (Map) 
import qualified Data.Map as Map  --required for GHCI  

myMap :: Integer -> Map Integer [Integer] 
myMap n = Map.fromList (map makePair [1..n]) 
   where makePair x = (x, [x])  

main = print(myMap 3)

Aşağıdaki çıktıyı üretecektir -

fromList [(1,[1]),(2,[2]),(3,[3])]

Modülü Ayarla

Set modülü, matematiksel verileri işlemek için bazı çok yararlı önceden tanımlanmış işlevlere sahiptir. Bir küme ikili ağaç olarak uygulanır, bu nedenle bir kümedeki tüm elemanlar benzersiz olmalıdır.

Aşağıdaki örnek koda bir göz atın

import qualified Data.Set as Set   

text1 = "Hey buddy"   
text2 = "This tutorial is for Haskell"   

main = do  
   let set1 = Set.fromList text1   
       set2 = Set.fromList text2 
   print(set1) 
   print(set2)

Burada, bir String'i Set'e dönüştürüyoruz. Aşağıdaki çıktıyı üretecektir. Çıktı kümesinin karakter tekrarı olmadığını gözlemleyin.

fromList " Hbdeuy"
fromList " HTaefhiklorstu"

Özel Modül

Bakalım diğer programlarda çağrılabilecek özel bir modülü nasıl oluşturabiliriz. Bu özel modülü uygulamak için, adında ayrı bir dosya oluşturacağız."custom.hs" Bizimle birlikte "main.hs".

Özel modülü oluşturalım ve içinde birkaç işlev tanımlayalım.

custom.hs

module Custom ( 
   showEven, 
   showBoolean 
) where 

showEven:: Int-> Bool 
showEven x = do 

if x 'rem' 2 == 0 
   then True 
else False 
showBoolean :: Bool->Int 
showBoolean c = do 

if c == True 
   then 1 
else 0

Özel modülümüz hazır. Şimdi onu bir programa aktaralım.

main.hs

import Custom 

main = do 
   print(showEven 4) 
   print(showBoolean True)

Kodumuz aşağıdaki çıktıyı üretecektir -

True
1

showEven fonksiyon döner True, "4" çift sayı olduğu için. showBoolean Fonksiyona aktardığımız Boolean fonksiyonu "True" olduğu için fonksiyon "1" döndürür.

Şimdiye kadar tartıştığımız tüm örnekler doğası gereği statiktir. Bu bölümde, kullanıcılarla dinamik olarak iletişim kurmayı öğreneceğiz. Haskell'de kullanılan farklı girdi ve çıktı tekniklerini öğreneceğiz.

Dosyalar ve Akışlar

Şimdiye kadar programın içindeki tüm girdileri sabit kodladık. Statik değişkenlerden girdi alıyoruz. Şimdi, harici bir dosyadan okumayı ve yazmayı öğrenelim.

Bir dosya oluşturalım ve "abc.txt" olarak adlandıralım. Ardından, bu metin dosyasına şu satırları girin: "Tutorialspoint'e hoş geldiniz. Burada Haskell'i öğrenmek için en iyi kaynağı bulacaksınız."

Ardından, bu dosyanın içeriğini konsolda gösterecek olan aşağıdaki kodu yazacağız. Burada, bir EOF karakteri bulana kadar bir dosyayı okuyan readFile () işlevini kullanıyoruz.

main = do  
   let file = "abc.txt" 
   contents <- readFile file 
   putStrLn contents

Yukarıdaki kod parçası, "abc.txt" dosyasını herhangi bir Dosya Sonu karakteriyle karşılaşana kadar Dize olarak okuyacaktır. Bu kod parçası aşağıdaki çıktıyı üretecektir.

Welcome to Tutorialspoint
Here, you will get the best resource to learn Haskell.

Terminalde yazdırdığı her şeyin o dosyaya yazıldığını gözlemleyin.

Komut Satırı Değişkeni

Haskell ayrıca tesisin komut istemi aracılığıyla bir dosyayı çalıştırmasını sağlar. Terminalimize geri dönelim ve yazalım"ghci". Ardından, aşağıdaki komut setini yazın -

let file = "abc.txt" 
writeFile file "I am just experimenting here." 
readFile file

Burada "abc.txt" adlı bir metin dosyası oluşturduk. Ardından, komutunu kullanarak dosyaya bir ifade ekledik.writeFile. Son olarak komutunu kullandıkreadFiledosyanın içeriğini konsolda yazdırmak için. Kodumuz aşağıdaki çıktıyı üretecektir -

I am just experimenting here.

İstisnalar

Bir exceptionkodda bir hata olarak kabul edilebilir. Derleyicinin çalışma zamanında beklenen çıktıyı alamadığı bir durumdur. Diğer tüm iyi programlama dilleri gibi Haskell de istisna işlemeyi uygulamak için bir yol sağlar.

Java'ya aşina iseniz, o zaman genellikle bir hata attığımız ve aynı şeyi catchblok. Haskell'de, çalışma zamanı hatalarını yakalamak için de aynı işleve sahibiz.

Fonksiyon tanımı try"try :: Exception e => IO a -> IO (Her ikiside)" gibi görünür. Aşağıdaki örnek koda bir göz atın. "Sıfıra Böl" istisnasını nasıl yakalayabileceğinizi gösterir.

import Control.Exception 

main = do 
   result <- try (evaluate (5 `div` 0)) :: IO (Either SomeException Int) 
   case result of 
      Left ex   -> putStrLn $ "Caught exception: " ++ show ex 
      Right val -> putStrLn $ "The answer was: " ++ show val

Yukarıdaki örnekte, dahili olarak kullandık try işlevi Control.Exceptionmodül, dolayısıyla istisnayı önceden yakalıyoruz. Yukarıdaki kod parçası ekranda aşağıdaki çıktıyı verecektir.

Caught exception: divide by zero

FunctorHaskell'de, üzerinde eşleştirilebilen farklı Türlerin bir tür işlevsel temsilidir. Polimorfizmi uygulamaya yönelik üst düzey bir kavramdır. Haskell geliştiricilerine göre Liste, Harita, Ağaç vb. Tüm Türler Haskell Functor örneğidir.

Bir Functor gibi bir fonksiyon tanımına sahip dahili bir sınıftır -

class Functor f where 
   fmap :: (a -> b) -> f a -> f b

Bu tanımla, şu sonuca varabiliriz: Functor bir işlevi alan bir işlevdir. fmap()ve başka bir işlev döndürür. Yukarıdaki örnekte,fmap() fonksiyonun genelleştirilmiş bir temsilidir map().

Aşağıdaki örnekte Haskell Functor'ın nasıl çalıştığını göreceğiz.

main = do  
   print(map (subtract 1) [2,4,8,16])      
   print(fmap (subtract 1) [2,4,8,16])

Burada ikisini de kullandık map() ve fmap()çıkarma işlemi için bir liste üzerinde. Her iki ifadenin de [1,3,7,15] öğelerini içeren bir listenin aynı sonucunu vereceğini gözlemleyebilirsiniz.

Her iki işlev de başka bir işlev olarak adlandırılır subtract() sonucu vermek için.

[1,3,7,15]
[1,3,7,15]

Öyleyse arasındaki fark nedir map ve fmap? Fark, kullanımlarında yatmaktadır. Functor "sadece" ve "Hiçbir şey" gibi farklı veri türlerinde daha fazla işlevselci uygulamamızı sağlar.

main = do 
   print (fmap  (+7)(Just 10)) 
   print (fmap  (+7) Nothing)

Yukarıdaki kod parçası, terminalde aşağıdaki çıktıyı verecektir -

Just 17
Nothing

Uygulayıcı Functor

Bir Uygulayıcı İşleci, Uygulayıcı Tür Sınıfı tarafından sağlanan bazı ekstra özelliklere sahip normal bir İşleçtir.

Functor kullanarak, genellikle var olan bir işlevi, içinde tanımlanan başka bir işlevle eşleriz. Ancak, bir Functor içinde başka bir Functor ile tanımlanan bir işlevi eşlemenin herhangi bir yolu yoktur. Bu yüzden adında başka bir tesisimiz var.Applicative Functor. Bu haritalama kolaylığı, aşağıda tanımlanan Uygulama Tipi sınıfı tarafından uygulanır.Controlmodül. Bu sınıf bize çalışmamız için yalnızca iki yöntem verir:pure ve diğeri <*>.

Aşağıda, Applicative Functor'ın sınıf tanımı yer almaktadır.

class (Functor f) => Applicative f where   
   pure :: a -> f a   
   (<*>) :: f (a -> b) -> f a -> f b

Uygulamaya göre, iki yöntem kullanarak başka bir Functor'u eşleyebiliriz: "Pure" ve "<*>". "Pure" yöntemi herhangi bir türden bir değer almalıdır ve her zaman bu değere sahip bir Applicative Functor döndürür.

Aşağıdaki örnek, bir Applicative Functor'ın nasıl çalıştığını gösterir -

import Control.Applicative 

f1:: Int -> Int -> Int 
f1 x y = 2*x+y  
main = do  
   print(show $ f1 <$> (Just 1) <*> (Just 2) )

Burada, fonksiyonun fonksiyon çağrısında uygulanabilir functors uyguladık f1. Programımız aşağıdaki çıktıyı verecektir.

"Just 4"

Monoidler

Haskell'in her şeyi işlevler biçiminde tanımladığını hepimiz biliyoruz. Fonksiyonlarda, girdimizi fonksiyonun çıktısı olarak alma seçeneklerimiz vardır. Bu neMonoid dır-dir.

Bir Monoidçıktının girdisinden bağımsız olduğu bir dizi işlev ve işleçtir. Bir fonksiyon (*) ve bir tam sayı (1) alalım. Şimdi, girdi ne olursa olsun, çıktısı yalnızca aynı sayıda kalacaktır. Yani, bir sayıyı 1 ile çarparsanız, aynı sayıyı elde edersiniz.

İşte monoidin Tip Sınıfı tanımı.

class Monoid m where  
   mempty :: m 
   mappend :: m -> m -> m  
   mconcat :: [m] -> m 
   mconcat = foldr mappend mempty

Haskell'de Monoid kullanımını anlamak için aşağıdaki örneğe bir göz atın.

multi:: Int->Int 
multi x = x * 1 
add :: Int->Int 
add x = x + 0 

main = do  
   print(multi 9)  
   print (add 7)

Kodumuz aşağıdaki çıktıyı üretecektir -

9
7

Burada, "multi" işlevi girişi "1" ile çarpar. Benzer şekilde, "ekle" işlevi girişi "0" ile ekler. Her iki durumda da çıkış, girişle aynı olacaktır. Dolayısıyla işlevler{(*),1} ve {(+),0} monoidlerin mükemmel örnekleridir.

Monadsbazı ekstra özelliklere sahip bir Uygulama İşlevi türünden başka bir şey değildir. Olarak bilinen üç temel kuralı yöneten bir Type sınıfıdır.monadic rules.

Üç kuralın tümü, aşağıdaki gibi bir Monad beyanı için kesinlikle geçerlidir:

class Monad m where  
   return :: a -> m a 
   (>>=) :: m a -> (a -> m b) -> m b 
   (>>) :: m a -> m b -> m b 
   x >> y = x >>= \_ -> y 
   fail :: String -> m a  
   fail msg = error msg

Bir Monad beyannamesi üzerinde geçerli olan üç temel yasa şunlardır:

  • Left Identity Law - returnişlevi değeri değiştirmez ve Monad'da hiçbir şeyi değiştirmemelidir. "Return> => mf = mf" olarak ifade edilebilir.

  • Right Identity Law - returnişlevi değeri değiştirmez ve Monad'da hiçbir şeyi değiştirmemelidir. "Mf> => return = mf" olarak ifade edilebilir.

  • Associativity- Bu yasaya göre, hem Functors hem de Monad örneği aynı şekilde çalışmalıdır. Matematiksel olarak "(f> ==> g)> => h = f> => (g> = h)" şeklinde ifade edilebilir.

İlk iki yasa aynı noktayı yineler, yani a return her iki tarafında da kimlik davranışı olmalıdır bind Şebeke.

Daha önceki örneklerimizde Monad olduklarını fark etmeden birçok Monad kullandık. Belirli bir liste oluşturmak için List Monad kullandığımız aşağıdaki örneği düşünün.

main = do
   print([1..10] >>= (\x -> if odd x then [x*2] else []))

Bu kod aşağıdaki çıktıyı üretecektir -

[2,6,10,14,18]

Zippers Haskell'de temelde veri yapısının belirli bir konumuna işaret eden işaretçiler vardır. tree.

Bir düşünelim tree 5 elemente sahip olmak [45,7,55,120,56]mükemmel bir ikili ağaç olarak gösterilebilir. Bu listenin son öğesini güncellemek istersem, onu güncellemeden önce son öğeye ulaşmak için tüm öğeleri geçmem gerekir. Sağ?

Ama ya ağacımızı bir sahip olma ağacının N öğeler bir koleksiyondur [(N-1),N]. O halde, tüm istenmeyen şeylerden geçmemize gerek yok.(N-1)elementler. Doğrudan N. elementi güncelleyebiliriz. Bu tam olarak Fermuar kavramıdır. Ağacın tamamını dolaşmadan bu değeri güncelleyebileceğimiz bir ağacın belirli bir konumuna odaklanır veya işaret eder.

Aşağıdaki örnekte, bir Listede Fermuar kavramını uyguladık. Aynı şekilde, Fermuar'ı birtree veya a file veri yapısı.

data List a = Empty | Cons a (List a) deriving (Show, Read, Eq, Ord)
type Zipper_List a = ([a],[a])    

go_Forward :: Zipper_List a -> Zipper_List a   
go_Forward (x:xs, bs) = (xs, x:bs)   
   
go_Back :: Zipper_List a -> Zipper_List a   
go_Back (xs, b:bs) = (b:xs, bs)    

main = do 
   let list_Ex = [1,2,3,4] 
   print(go_Forward (list_Ex,[]))       
   print(go_Back([4],[3,2,1]))

Yukarıdaki programı derleyip çalıştırdığınızda, aşağıdaki çıktıyı üretecektir -

([2,3,4],[1]) 
([3,4],[2,1])

Burada, ileri giderken veya geri giderken tüm dizginin bir öğesine odaklanıyoruz.