Haskell/Witaj inny świecie

Z Wikibooks, biblioteki wolnych podręczników.

Spis treści

[edytuj] Kompilatory i interpretery

Kod napisany w języku Haskell może być wykonywany w trybie wsadowym (kompilowanie) lub interaktywnym (interpretowanie). Tryb interaktywny jest doskonałym rozwiązaniem do eksperymentowania i nauki. Istnieją trzy najpopularniejsze implementacje języka Haskell:

  • Hugs - bardzo szybki interpreter, nie pozwala na utworzenie samodzielnych programów oraz na definiowanie funkcji w środowisku (tylko w plikach). Dostępny dla większości systemów operacyjnych.
  • GHC - wolniejszy niż Hugs. Pozwala na interpretacje programów oraz kompilację. Umożliwia definiowanie funkcji w środowisku. Dobre wsparcie dla stosowania funkcji z innych języków.
  • NHC - rzadko stosowany. Umożliwia jedynie kompilowanie programów. Tworzy małe i szybkie pliki wykonywalne.

W dalszej części stosowany będzie GHC - Glasgow Haskell Compiler, dostępny pod adresem http://haskell.org/ghc. Interpreter uruchamiamy poleceniem ghci lub ghc interactive. Po uruchomieniu na ekranie pojawia się ekran powitalny, oraz linia poleceń (Prelude>). Aby zakończyć działanie ghci w lini poleceń wpisujemy :quit.

[edytuj] Witaj świecie!

Naukę nowego języka programowania najczęściej zaczyna się od programu wypisującego na ekranie powitanie „Witaj świecie!”. W Haskellu można to zrobić na kilka sposobów: Wpisując bezpośrednio w linii poleceń łańcuch znaków ograniczony cudzysłowami

 Prelude> "Witaj swiecie"
 "Witaj swiecie"

Interpreter „obliczy” wartość podanego wyrażenia – łańcucha znaków – i wypisze ją. Innym sposobem jest wypisanie łańcucha znaków bezpośrednio na standardowe wyjście:

Prelude> putStrLn "Witaj swiecie"
Witaj swiecie

Używając GHC można skompilować kod do pliku wykonywalnego poleceniem: $ ghc -o witaj witaj.hs oraz uruchomić

$ ./witaj
"Witaj swiecie"

[edytuj] Komentarze

Podobnie jak większość języków programowania Haskell umożliwia umieszczanie wewnątrz kodu komentarzy, które są ignorowane przez kompilator (lub interpreter). Komentarz może się składać z jednej linii tekstu:

-- komentarz w jednej linii

lub z większego fragmentu tekstu

{- 
dłuższy komentarz
składający się
z kilku linii
-}

[edytuj] Obliczanie silni

Poprzedni program nie jest jednak najlepszym programem do rozpoczęcia nauki języka funkcyjnego. Kolejny przykład będzie już bardziej typowy dla tej grupy języków. Będzie to funkcja wyznaczająca wartość silni. Jedno z możliwych rozwiązań wygląda następująco:

Prelude> let silnia n = if n == 0 then 1 else n * silnia (n-1)

Za pomocą słowa let zdefiniowana została funkcja silnia przyjmująca jeden parametr n. Następnie wykorzystana została instrukcja warunkowa:

if warunek then wartość1 else wartość2

która w zależności od tego czy warunek został spełniony zwróci wartość1 lub wartość2. Funkcję silnia można zdefiniować w osobnym pliku i załadować do GHCi. W tym celu należy utworzyć plik silnia.hs. W pliku tym można umieścić taką definicją funkcji jaka została przedstawiona powyżej, ale bez słowa let, które jest poleceniem interpretera, a nie elementem języka. Można nieco ją zmienić tą definicję, dzięki czemu będzie wyglądała bardziej elegancko:

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

Pierwsza linia nie jest obowiązkowa, określa ona typ wartości przyjmowanej i zwracanej przez funkcję silnia. Chociaż określenie typów nie jest wymagane, warto je stosować jako dokumentację kodu. Określanie typów często pomaga w lokalizowaniu błędów. Nazwy typów w Haskellu zaczynają się od wielkiej litery. Funkcje zdefiniowane w pliku silnia.hs można załadować do interpretera za pomocą polecenia :load (lub krócej :l) i używać w następujący sposób:

Prelude> :load silnia.hs
[1 of 1] Compiling Main			( silnia.hs, interpreter )
Ok., module loaded: Main.
*Main> silnia 4
24

Dopisanie na końcu pliku silnia.hs jeszcze jednej linii

main = print (silnia 4)

pozwoli na skompilowanie tego pliku i utworzenie pliku wykonywalnego

$ ghc -o silnia silnia.hs
$ ./silnia
24

Funkcja print odpowiada za konwersję wartości Int do wartości String

Porada Ćwiczenie
  1. Napisz funkcję przyjmującą jako parametr liczbę całkowitą n i wyznaczającą sumę dodatnich liczb parzystych mniejszych lub równych n (reszta z dzielenia liczby a przez b uzyskujemy za pomocą: mod a b).
  2. Napisz funkcję znajdującą największy wspólny dzielnik dla dwóch dodatnich liczb całkowitych.
  3. Napisz funkcję wyznaczającą (z definicji) n-ty element ciągu Fibbonacciego.