Haskell/Zmienne i funkcje
Z Wikibooks, biblioteki wolnych podręczników.
[edytuj] Zmienne
Interpreter GHCi pozwala na wykonywanie operacji arytmetycznych poprzez bezpośrednie wpisanie ich w linii poleceń interpretera. Na przykład można obliczyć pole koła o promieniu 5 w następujący sposób:
Prelude> 3.14159265358979323846264338327950 * 5 * 5 78.53981633974483
Jeśli następnie chcielibyśmy obliczyć obwód tego koła, konieczne było by ponowne wpisanie wartości liczby pi. GHCi pozwala na definiowanie zmiennych za pomocą słowa let. Po jednokrotnym zdefiniowaniu wartości pi można używać jej w dalszych obliczeniach. Nazwy zmiennych (oraz funkcji) muszą rozpoczynać się od małej litery.
Prelude> let pi = 3.14159265358979323846264338327950 Prelude> pi 3.141592653589793
Liczba pi jest „obcinana” do 16 cyfr jedynie podczas wyświetlania.
Prelude> pi * 5 * 5 78.53981633974483
Jeśli chcielibyśmy również promień zastąpić zmienną r możemy napotkać pewien problem.
Prelude> let r = 5
Prelude> pi*r*r
<interactive>:1:5:
Couldn't match expected type `Double'
against `Integer'
Expected type: Double
Inferred type: Integer
In the second argument of `(*)', namely `r'
In the first argument of `(*)', namely `r', namely `pi * r'
Problem ten spowodowany jest ścisłą kontrolą zgodności typów, a dokładniej tym, że Haskell nie pozwala na pomnożenie liczby typu Double przez liczbę typu Integer. Rozwiązaniem tego problemu może być zdefiniowanie zmiennej r jako liczby rzeczywistej:
Prelude> let r = 5.0
Zmienne nie muszą być definiowane bezpośrednio jako liczby. Mogą być zdefiniowane na przykład jako wyrażenie arytmetyczne:
Prelude> let poleKola = pi * r * r Prelude> poleKola 78.53981633974483
Należy jednak pamiętać, że wartość zmiennej jest niezmienna. Niemożliwe jest więc obliczenie pola koła o promieniu 2 w następujący sposób:
Prelude> let r = 2.0 Prelude> poleKola 78.53981633974483
[edytuj] Funkcje
Wygodnym rozwiązaniem tego problemu jest zdefiniowanie funkcji przyjmującej jako parametr długość promienia koła.
Prelude> let poleKola r = pi * r * r Prelude> poleKola 5 78.53981633974483 Prelude> poleKola 1 3.141592653589793
Zmienna r wewnątrz funkcji poleKola jest zmienną lokalną. Wartość zmiennej globalnej o tej samej nazwie nie ma żadnego wpływu na działanie funkcji.
Warto zauważyć, że tym razem możliwe jest obliczenie pola koła o promieniu 5 (nie musi to być 5.0). Typ wartości liczbowej jest ustalany na podstawie kontekstu w jakim występuje. Podczas definicji zmiennej r nie było możliwe wywnioskowanie, że ma to być liczba rzeczywista. Podczas wywołania funkcji poleKola z parametrem jest to możliwe. Parametr przekazany do funkcji jest mnożony przez liczbę rzeczywistą (pi), więc powinien być liczbą tego samego typu. Dzięki temu Haskell traktuje liczbę 5 jako Double.
Oczywiście możliwe jest zdefiniowanie funkcji przyjmującej więcej niż jeden parametr, na przykład obliczającej pole prostokąta:
Prelude> let poleProstokata a b = a * b Prelude> poleProstokata 2 4 8
Można również zdefiniować funkcję, która do wyznaczenia wartości wykorzysta inne funkcje. Na przykład funkcja licząca objętość prostopadłościanu
Prelude> let objProstopadloscianu a b h = poleProstokata a b * h Prelude> objProstopadloscianu 1 2 3 6
[edytuj] Funkcje liczące pola graniastosłupów
Powyżej zostały zdefiniowane funkcje obliczające pole koła i prostokąta. Na ich podstawie w prosty sposób można zdefiniować funkcje wyznaczające objętość różnych graniastosłupów. Objętość dowolnego graniastosłupa obliczamy mnożąc pole podstawy razy wysokość. Na początek napiszmy więc taką funkcję:
Prelude> objGran polePodst h = polePodst * h
Teraz możemy już zdefiniować funkcje liczącą objętość prostopadłościanu, walca lub sześcianu:
Prelude> let objProstopadloscianu a b h = objGran (poleProstokata a b) h Prelude> let objWalca r h = objGran (poleKola r) h Prelude> let objSzescianu a = objGran (poleProstokata a a) a