Autor: 26.06.2023
Funkcje w języku Haskell
Haskell to niszowy, ale niezwykle ciekawy język funkcyjny. A funkcje są podstawowym blokiem budującym aplikacje w tym języku. Z tym artykułem poznasz najważniejsze techniki pracy z funkcjami.
Deklarowanie funkcji
W języku Haskell funkcja to wydzielony fragment kodu, którego możemy wielokrotnie użyć. Zapobiega to niepotrzebnemu powielaniu naszej pracy.
Spójrz, jak wygląda deklaracja funkcji:
add :: Integer -> (Integer -> Integer)
Dziwne znaczki, prawda? O co tutaj chodzi?
Zacznijmy od początku. Deklarujemy, że funkcja:
- Będzie się nazywała add (po nazwie funkcji nie zapomnij o znakach ::),
- Będzie zwracała wartość całkowitą Integer,
- Będzie przyjmowała 2 parametry wejściowe: (Integer -> Integer)
To jest tylko deklaracja. Informujemy, że taka funkcja będzie istniała. Jeszcze nie zaimplementowaliśmy dokładnie, co będzie robiła. Po nazwie jesteśmy w stanie stwierdzić, że taka funkcja będzie zajmowała się dodawaniem liczb całkowitych. Nic poza tym.
W takim razie przyjrzymy się definicji funkcji add():
add digitX digitY = digitX + digitY
Powyższy przykład to definicja. Słowo kluczowe add to oczywiście nazwa naszej funkcji. Po nazwie funkcji znajdują się tzw. parametry wejściowe. Zadeklarowaliśmy, że będą to dwa parametry, więc mamy dwa. Po znaku = mamy ciało funkcji, która realizuje odpowiednie działania. W naszym przypadku funkcja miała zająć się dodawaniem dwóch liczb całkowitych, więc to robi.
Użyjmy naszej funkcji
Gdy już zaprojektowaliśmy naszą funkcję to dopiero teraz możemy jej użyć. Mamy przygotowaną deklarację oraz definicję. Teraz nie pozostaje nam nic innego, jak ją wywołać i przetestować w praktyce.
Wywołanie funkcji polega na użyciu nazwy naszej utworzonej funkcji i podaniu odpowiednich parametrów, które chcemy wykorzystać do obliczeń. Chcemy dodać dwie liczby całkowite 2 i 4. Nic trudnego. Sprawdźmy obliczenia na praktycznym przykładzie:
print("Add two params: ")
let result = add 2 4
print(result)
Do zmiennej result przypisujemy wynik naszej operacji. Nasza operacja to dodawanie dwóch liczb całkowitych. Po znaku = wywołujemy naszą funkcję, czyli podajemy jej nazwę add, a po nazwie podajemy listę parametrów: 2 i 4.
Rezultat naszych działań zostanie zaprezentowany na wyjściu:
"Add two params: "
6
Ostatecznie nasz kod powinien prezentować się w następujący sposób:
add :: Integer -> (Integer -> Integer) -- declaration
add digitX digitY = digitX + digitY -- definition
main = do
print("Add two params: ")
let result = add 2 4 -- usage
print(result)
Wywołanie funkcji add() odbywa się w następujący sposób:
let result = add 2 4
Z definicji funkcji add() możemy wywnioskować, że:
digitX = 2
digitY = 4
Podstawiając pod wzór definicji funkcji mamy następujący rezultat działań:
add digitX digitY = digitX + digitY
Nadajemy naszym zmiennym wartości
add 2 4 = 2 + 4
Ostatecznie otrzymamy:
add 2 4 = 6
Skoro doszliśmy do takiego wyniku, spójrzmy jeszcze raz na cały kod:
add :: Integer -> (Integer -> Integer) -- declaration
add digitX digitY = digitX + digitY -- definition
main = do
print("Add two params: ")
let result = add 2 4 -- usage
print(result)
Teraz wystarczy podstawić za add 2 4 cyfrę 6. Wynik naszych obliczeń jest identyczny z wynikiem działania programu:
6
Przykłady funkcji wbudowanych
W języku Haskell mamy gotowe funkcje, które możemy wywoływać. Nie musimy implementować wszystkiego od początku. Oto kilka funkcji z dużymi możliwościami.
W języku Haskell występuje funkcja head(), która zwraca pierwszy element listy (czyli head).
main = do
let list = [3, 1, 2]
let firstElement = head list
print firstElement
Funkcja head() zwraca pierwszy element listy, więc program działa zgodnie z oczekiwaniami:
3
Kolejna funkcja operująca na listach to tail(). Jej zadaniem jest wyszukiwanie ciała listy, czyli wszystkich elementów z wyłączeniem głowy (pierwszego elementu). Spójrz na przykład:
main = do
let list = [3, 1, 2]
let body = tail list
print body
Rezultat jest zgodny z naszymi oczekiwaniami:
[1, 2]
Funkcja last(), jak sama nazwa wskazuje, będzie w stanie zwrócić ostatni element listy. Spójrzmy jak działa w praktyce.
main = do
let list = [3, 1, 2]
let lastElement = last list
print lastElement
Oczywiście funkcja działa zgodnie z założeniami:
2
Kolejne przykłady wbudowanych funkcji
Nie będziemy prezentowali wszystkich możliwych funkcji, gdyż ich wywołania są praktycznie identyczne. Spójrzmy na tabelę prezentującą inne ciekawe funkcje operujące na listach w języku Haskell.
Funkcje:
Init
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (init [1, 2, 3]) | Zwraca elementy listy oprócz ostatniego (działanie odwrotne do funkcji tail()). |
Reverse
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (reverse [1, 2, 3]) | Odwraca kolejność elementów listy. Ostatni element staje się pierwszym elementem itd. |
Length
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (length [1, 2, 3]) | Zwraca liczbę elementów listy. |
Maximum
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (maximum [1, 2, 3]) | Zwraca największy element listy. |
Minimum
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (minimum [1, 2, 3]) | Zwraca najmniejszy element listy. |
Sum
Przykładowe wywołanie | Co robi funkcja? |
---|---|
main = print (sum [1, 2, 3]) | Sumuje elementy listy. |
Funkcje, które zaprezentowaliśmy to jest tylko mały wycinek. Język Haskell oferuje o wiele więcej, ale nie jesteśmy fizycznie w stanie wszystkiego pokazać.
Podsumowanie
Funkcje to fundamentalny element języka Haskell. Masz możliwość tworzenia własnych funkcji, masz też do dyspozycji szeroki zestaw funkcji wbudowanych.
Chcesz dowiedzieć się więcej na temat funkcji oraz innych technik programowania w tym języku? Zapraszamy na polski kurs Fundamenty Haskell Level 1.