Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałPrzemek Polak Został zmieniony 9 lat temu
1
Krakowski Piotr, Woliński Radosław, Kowalski Piotr, Machowski Michał
2
Aby zacząć pracę z językiem Haskell musimy mieć zainstalowany interpreter oraz kompilator o nazwie ghc. Można go otworzyć na dwa sposoby: Otwierając aplikację GHCI lub uruchamiając konsolę poleceniem cmd i wpisując w niej komendę ghci. Poprawnie uruchomiony interpreter wygląda tak:
3
W linijce Prelude> wpisujemy wyrażenia. Istnieje oczywiście możliwość zmiany nazwy Prelude>, wykonu się to poleceniem :set prompt „nazwa >” W języku Haskell możemy używać oczywiście operatorów matematycznych: +, -, *,/,^ Możemy również skorzystać z kilku operatorów w jednej linii, a Haskell obliczając je zachowa kolejność.
4
W języku Haskell można również zastosować algebrę Boole’a czyli True i False, oraz znaki wartości logicznych: && - oznacza i || - oznacza lub Do zaprzeczania wyrażenia stosujemy słowo not Jeżeli porównujemy jakieś wyrażenia ze sobą muszą być one tego samego typu.
5
Przyjrzyjmy się teraz najpopularniejszym funkcjom w języku haskell. Funkcje jakie występują są infiksowe oraz prefiksowe. Istnieje możliwość użycia funkcji prefiksowej jako infiksową, aby to zrobić funkcję prefiksową trzeba napisać niędzy znakami `` np.: 9 `mod` 2. Przykłady funkcji: ◦ Succ – następnik po danym wyrażeniu ◦ Pred – poprzednik przed danym wyrażeniem ◦ Odd – sprawdza czy nieparzysta ◦ Even – sprawdza czy parzysta ◦ Min – zwraca mniejszą z danych liczb ◦ Max – zwraca większą z danych liczb
6
Funkcję w języku haskell zapisujemy w pliku o rozszerzeniu.hs, plik możemy utworzyć w dowolnym edytorze tekstu. Schemat funkcji wygąda następująco: ◦ Nazwa_funkcji x = wyrażenie z x. Przykład funkcji: Podwojona x = x+x Aby użyć funkcji zapisujemy nasz plik.hs i otwieramy go w dwojaki sposób: Poprzez dwukrotne kliknięcie na niego lub poprzez otwarcie interpretera ghc i wpisanie polecenia :l sciezka_pliku_hs
7
Istnieje również możliwość użycia instrukcji warunkowej if np.: Podwojona` x = if x < 100 then x^2 else x W języku Haskell if zawsze musi być w parze z else, nie można pominąć esle jak i innych językach.
8
Listy - jest to struktura, która może przechowywać dane, w języku Haskell listy są jednorodne, czyli mogą przechowywać tylko i wyłącznie dane jednego typu. Przykład listy: ◦ [1,2,3,4,5,6] ◦ [‘a’,’b’,’c’] ◦ [[1,2,3,],[3,4,5,]]
9
Ciekawą funkcją w języku Haskell jest funkcja let która pozwala przypisać wartość do nazwy, np.: przy użyciu polecenia: let tab = [1,2,3] do nazwy tab zostanie przypisana lista. Operatory pozwalające działać na listach: ◦ ++ - łączy elementy z list ◦ : - dodaje element na początek listy ◦ !! – wypisuje element z danej pozycji
10
Listy można również ze sobą porównywać w tym celu używa się następujących operatorów: ◦ < - mniejsze ◦ <= - mniejsze bądź równe ◦ >- większe ◦ >= - większe bądź równe ◦ == - porównanie Do list możemy użyć jeszcze kilku ciekawych funckji: ◦ Head – zwraca pierwszy element z listy ◦ Tail – zwraca elementy oprócz pierwszego ◦ Last - zwraca ostatni element listy
11
Radosław Woliński
12
Przyjmuje listę i zwraca wszystko oprócz ostatniego elementu ghci> init [5, 4, 3, 2, 1] [5, 4, 3, 2] Funkcja init przyjmuje jako parametr listę i zwraca wszystko oprócz jego ostatniego elementu.
13
Podczas używania z funkcji head, tail, last, init należy zwrócić szczególną uwagę na użycie ich do pustych list. Ponieważ błąd z nimi związany nie będzie wykryty podczas kompilacji.
14
Length przyjmuję jako parametr listę i zwraca jej długość: ghci > length [5,4,3,2,1] 5 Null sprawdza czy lista jest pusta ghci > null [1,2,3] False ghci > null [] True
15
Reverse odwraca listę ghci > reverse [5,4,3,2,1] [1,2,3,4,5] Take przyjmuje liczbę oraz listę, liczba jest ilością indeksów w tablicy które zostaną wydobyte i wypisane (od początku tablicy) ghci > take 3 [5,4,3,2,1] [5,4,3] ghci > take 1 [3,9,3] [3]
16
Drop działa podobnie do take z tym, że wyrzuca z listy podaną liczbę elementów. Jeżeli spróbujemy upuścić więcej elementów niż zawiera tablica otrzymamy pustą tablicę. ghci > drop 3 [8,4,2,1,5,6] [1,5,6] ghci > drop 0 [1,2,3,4] [1,2,3,4] ghci > drop 100 [1,2,3,4] []
17
Maximum oraz minimum zwracają największy oraz najmniejszy element z tablicy ghci > minimum [8,4,2,1,5,6] 1 ghci > maximum [1,9,2,3,4] 9 Sum pobiera listę i zwraca sumę elementów w liście, a product mnoży je ghci > sum [5,2,1,6,3,2,5,7] 31 ghci > product [6,2,1,2] 24
18
Elem jako argumenty przyjmuje liczbę oraz listę, a następnie sprawdza czy liczba jest elementem w tablicy. ghci > 4 `elem ` [3,4,5,6] True ghci > 10 `elem ` [3,4,5,6] False Ten zapis nazywany jest zapisem infixowym, funkcję można również zapisać w postaci ghci > elem 10 [3,4,5,6] False Niestety taki zapis jest nieczytelny. Zapisu infixowego można używać do wszystkich funckji, często poprawia czytelność, aby go użyć najpierw podajemy argument potem nazwę funkcji w `` i drugi argument.
19
Zakresy pozwalają tworzyć listy posiadające arytmetyczne sekwencje elementów, które mogą być wymienione (np. zakres od 1 do 20 itp.). Można również stworzyć zakres dla liter. Aby stworzyć listę z zakresem wystarczy użyć dwóch kropek pomiędzy pierwszym i ostatnim elementem tablicy (tak więc [1..20] wpisane w konsoli wypisze na ekranie listę liczbową z zakresu od 1 do 20).
20
Zapis ghci > [1..20] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] Jest równoznaczny z tym gdybyśmy wypełnili listę ręcznie. Tworzenie list za pomocą zakresu pozwala również na utworzenie sekwencji, wystarczy określić pierwszy krok (i tylko pierwszy). ghci > [2,4..20] [2,4,6,8,10,12,14,16,18,20] Przy takim zapisie list należy jednak uważać stosując liczby zmiennoprzecinkowe, które nie są dokładne. Można tworzyć zakresy nieskończone. Aby uzyskać np. wielokrotność 13 ale tylko 24 kolejne liczby można zrobić to na dwa sposoby: [13,26..24*13] lub: take 24 [13,26..].
21
Cycle pobiera listę i zamienia ją na listę nieskończoną ghci > take 10 ( cycle [1,2,3]) [1,2,3,1,2,3,1,2,3,1] Repeat pobiera tylko jeden element i z niego tworzy nieskończoną listę ghci > take 10 ( repeat 5) [5,5,5,5,5,5,5,5,5,5] Dla ułatwienia można użyć funkcji replicate ghci > replicate 3 10 [10,10,10]
22
W przypadku gdy chcemy wypisać listę na której chcemy zastosować bardziej złożone funkcje, możemy użyć listy z zasięgiem np. aby wypisać 10 kolejnych liczby pomnożonych przez 2 możemy zapisać to w ten sposób: ghci > [x*2 | x <- [1..10]] [2,4,6,8,10,12,14,16,18,20]
23
Teraz możemy dodać warunek lub predykat, weźmy elementy które są większe lub równe 12. ghci > [x*2 | x = 12] [12,14,16,18,20] Wyeliminowanie list za pomocą predykatów nazywa się filtrowaniem. Można użyć wielu predykatów jeśli chcemy (element musi spełniać wszystkie predykaty). ghci > [ x | x <- [10..20], x /= 13, x /= 15, x /= 19] [10,11,12,14,16,17,18,20]
24
Możemy również użyć kilku list, podczas łączenia wielu list wynikiem jest kombinacja wszystkich jego elementów. ghci > [ x*y | x <- [2,5,10], y <- [8,10,11]] [16,20,22,40,50,55,80,100,110]
25
length ' xs = sum [1 | _ <- xs] Funkcja ta zamienia każdy element w liście na 1, a następnie je sumuje. _ oznacza, że nie ma dla nas znaczenia co znajduje się w liście ponieważ nie będziemy tego elementu nigdzie używać.
26
Ciągi znakowe (string) są traktowane jako listy, dlatego możemy użyć do nich operatora zasięgu. Poniżej funkcja usuwająca z listy wszystko prócz wielkich liter removeNonUppercase st = [ c | c <- st, c `elem ` ['A '.. 'Z ']] Testing it out: ghci > removeNonUppercase " Hahaha ! Ahahaha !" "HA" ghci > removeNonUppercase " IdontLIKEFROGS " " ILIKEFROGS "
27
Całą „pracę” wykonał predykat, który ustala, że w nowej liście może znajdować się jedynie element z listy ['A'..'Z']. Kolejny przykład to lista składająca się z list, chcemy usunąć liczby nieparzyste bez spłaszczania listy ghci > let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]] ghci > [ [ x | x <- xs, even x ] | xs <- xxs ] [[2,2,4],[2,4,6,8],[2,4,2,6,2,6]] Zasięgi listowe można pisać w kilku liniach, więc dla czytelności można podzielić na kilka linii jeśli nie piszemy w konsoli.
28
W pewnym sensie krotka to również lista, jest to sposób na przechowanie kilku wartości jako jednej. Istnieje jednak kilka różnica. Lista zawiera typ i nie ma znaczenia czy znajduje się w niej jedna liczba czy jest ich nieskończenie wiele. Krotki stosuje się do określonych wartości, a ich typ określa ile ma elementów i jaki jest typ tych elementów. Są oznaczane nawiasami okrągłymi, a ich elementy oddzielone są przecinkami, nie muszą być jednorodne. W przeciwieństwie do listy krotka może zawierać kilka typów.
29
Jeśli chcielibyśmy w Haskell’u zapisać parę liczb np. wektorów możemy zrobić to w ten sposób [[1,2],[8,11],[4,5]] problem w tym, że możemy przez pomyłkę napisać też tak [[1,2],[8,11,5],[4,5]], a Haskell nie będzie widział w tym problemu gdyż to poprawna lista. Chcielibyśmy otrzymać parę liczb jako oddzielny typ dlatego należy zrobić to w ten sposób [(1,2),(8,11),(4,5)]. Teraz pomyłka nie wchodzi w grę ponieważ przy zapisie [(1,2),(8,11,5),(4,5)] kompilator zwróci błąd.
30
Krotki mogą być używane do reprezentowania różnych danych np. ("Christopher", "Walken", 55). Jak widać mogą zawierać również listę. Krotki są bardziej sztywne ponieważ każda inna wielkość to nowy rodzaj, więc nie można napisać ogólnej funkcji dołączającej element do niej. Trzeba by napisać funkcję dołączającą element do pary, trójki itd..
31
Piotr Kowalski
59
Machowski Michał
60
Eq używany do testowania równości. Funkcje, które muszą implementować jego reprezentanci to == oraz /=. Jeśli jakaś funkcja operuje jedynie na reprezentantach Eq (co możesz odczytać z jej sygnatury), to prawdopodobnie korzysta z którejś z tych dwóch funkcji. Wszystkie typy jakie dotychczas poznaliśmy, oprócz funkcji, są reprezentantami Eq, a więc mogą być porównywane.
61
ghci> 5 == 5 True ghci> 5 /= 5 False ghci> 'a' == 'a' True ghci> "Ho Ho" == "Ho Ho" True ghci> 3.422 == 3.422 True
62
Funkcja compare przyjmuje dwoje reprezentantów Ord i zwraca typ Ordering, który może przyjmować wartości GT,LT i EQ, oznaczające odpowiednio większy, mniejszy i równy. Aby być reprezentantem typu Ord dany typ musi być wcześnoiej reprezentantem Eq.
63
ghci> "Abrakadabra" < "Zebra" True ghci> "Abrakadabra" `compare` "Zebra" LT ghci> 5 >= 2 True ghci> 5 `compare` 3 GT
64
Reprezentanci Show mogą zostać zamienione na łańcuch znaków. Najczęściej używaną funkcją operującą na reprezentantach Show jest show. Pobiera ona wartość będącą reprezentantem Show i zamienia ją na łańcuch znaków. ghci> show 3 "3" ghci> show 5.334 "5.334" ghci> show True "True„
65
ghci> read "True" || False True ghci> read "8.2" + 3.8 12.0 ghci> read "5" - 2 3 ghci> read "[1,2,3,4]" ++ [3] [1,2,3,4,3]
66
Read jest t-klasą komplementarną względem Show. Funkcja read pobiera łańcuch znaków i zwraca wartość będącą reprezentantem Read. ghci> read "True" || False True ghci> read "8.2" + 3.8 12.0 ghci> read "5" - 2 3 ghci> read "[1,2,3,4]" ++ [3] [1,2,3,4,3]
67
Read zwraca pewien typ reprezentujący Read, jednak jeśli nie użyjemy później tego wyrażenia nie sposób określić dokładnego typu o jaki chodzi. Do tego celu wykorzystuje sie jawne adnotacje typów. Adnotacje typów to sposób na jawne określenie jakiego typu powinno być dane wyrażenie. Przykłady: ghci> read "5" :: Int 5 ghci> read "5" :: Fload 5.0 ghci> (read "5" :: Float) * 4 20.0 ghci> read "[1,2,3,4]" :: [Int] [1,2,3,4] ghci> read "(3, 'a')" :: (Int, Char) (3, 'a')
68
Kompilator jest w stanie sam określić typ większości wyrażeń, jednak czasami nie jest w stanie stwierdzić, czy oczekiwaną wartością jest Int, czy Float, na przykład w wyrażeniu read "5". Aby określić typ tego wyrażenia Haskell musiałby je obliczyć, a ponieważ jest językiem ze statycznym systemem typów, musi znać wszystkie typy jeszcze przed procesem kompilacji (a więc tymbardziej przed obliczeniem jakiejkolwiek wartości). Właśnie dlatego musisz jawnie powiedzieć: "Hej, to wyrażenie ma taki a taki typ, na wypadek gdybyś nie wiedział!".
69
Reprezentanci Enum to typy, które poddają się wyliczeniu - mogą być wymienione w kolejności. Główną zaletą t- klasy Enum jest to, że jego reprezentantów można używać do tworzenia przedziałów. Każda wartość takiego typu ma też określonego następcę i poprzednika. Można je otrzymać wywołując odpowiednio funkcje succ i pred. Reprezentantami Enum są (), Bool,Char, Ordering, Int, Integer, Float i Double. ghci> ['a'..'e'] "abcde" ghci> [LT..GT] [LT, EQ, GT] ghci> [3.. 5] [3,4,5] ghci> succ 'B' 'C'
70
Reprezentanci Bounded to typy, które posiadają wartość najmniejszą i największą. ghci> minBound :: Int -2147483648 ghci> maxBound :: Char '\1114111' ghci> maxBound :: Bool True ghci> minBound :: Bool False
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.