Haskell/Stałe i funkcje
Stałe
edytujInterpreter 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 stałych za pomocą słowa kluczowego let. Po jednokrotnym zdefiniowaniu wartości pi można używać jej w dalszych obliczeniach. Nazwy stałych (oraz funkcji) muszą rozpoczynać się od małej litery.
Prelude> let pi = 3.14159265358979323846264338327950 Prelude> pi 3.141592653589793
Liczby są „obcinane” do 16 cyfr jedynie podczas wyświetlania.
Prelude> pi * 5 * 5 78.53981633974483
Jeśli chcielibyśmy również promień zastąpić stałą 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 stałej r jako liczby rzeczywistej:
Prelude> let r = 5.0
Stałe 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ść stałej jest niezmienna (tym się różni od występujących w innych językach tzw. zmiennych). 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
Stałą poleKola (podobnie jak inne stałe) można potraktować jak funkcję nieprzyjmującą żadnych parametrów. Zgodnie z zasadą referencyjnej przeźroczystości funkcja wywołana z takim samym zestawem parametrów (w tym przypadku lista parametrów jest pusta) zawsze zwróci tą samą wartość. Stała r jest globalna, a działanie funkcji nie może być zależne od żadnej stałej globalnej. |
Funkcje
edytujWygodnym 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
Stała r wewnątrz funkcji poleKola jest stałą lokalną. Wartość stałej 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 stałej 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
Funkcje liczące pola graniastosłupów
edytujPowyż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>let 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
Ćwiczenie
|