Haskell/Witaj inny świecie

Programy

edytuj

Implementacje

edytuj

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 - Pozwala na interpretacje programów (wolniej niż Hugs) oraz kompilację (bardzo szybki kod wynikowy). 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.

Dodatkowe programy

edytuj
  • narzędzia do tworzenie projektów
    • Cabal
    • stack
    • Halcyon
  • programy do tworzenia dokumentacji kodu
    • Haddock

Start i zakończenie

edytuj

Uruchamiamy GHC w trybie interaktywnym : linii poleceń wpisujemy :

ghci

Otrzymujemy :

GHCi, version 6.12.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude>


Wyjście z GHCI :

Prelude> :quit
Leaving GHCi

albo za pomocą skrótu klawiszowego control-D.

Sprawdzamy jaką wersję kompilatora mamy

ghc --info
[("Project name","The Glorious Glasgow Haskell Compilation System")
,("Project version","6.12.1")
,("Booter version","6.12.1")
,("Stage","2")
,("Have interpreter","YES")
,("Object splitting","YES")
,("Have native code generator","YES")
,("Support SMP","YES")
,("Unregisterised","NO")
,("Tables next to code","YES")
,("Win32 DLLs","")
,("RTS ways","l debug  thr thr_debug thr_l thr_p  dyn debug_dyn thr_dyn thr_debug_dyn")
,("Leading underscore","NO")
,("Debug on","False")
,("LibDir","/usr/lib/ghc-6.12.1")
]

cabal oznacza:[1]

  • program konsolowy do obsługi programów i bibliotek napisanych w języku Haskell = cabal-install ( aka Cabal-the-tool)
  • formatem plików zawierających informacje o projekcie/programie, np. my-project.cabal ( aka Cabal-the-spec )
  • bibliotekę ( framework) implementującą ww specyfikację ( aka Cabal-the-library )

Możemy korzystać z Haskella w Bashu za pośrednictwem stacka[2]

Przykład:[3]

  stack new hello-haskell
  cd hello-haskell
  stack setup
  stack build
  stack exec hello-haskell

Stacka wykorzystuje pliki:

  • stack.yaml
  • *.cabal

Witaj świecie!

edytuj

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"

Komentarze

edytuj

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
-}

Obliczanie silni

edytuj

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 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

  1. fpcomplete : why-is-stack-not-cabal
  2. stack w ang. wikipedii
  3. touk: getting-started-with-haskell-stack-and-spacemacs