Typy i typy klas.

Slides:



Advertisements
Podobne prezentacje
Temat 2: Podstawy programowania Algorytmy – 1 z 2 _________________________________________________________________________________________________________________.
Advertisements

Proces doboru próby. Badana populacja – (zbiorowość generalna, populacja generalna) ogół rzeczywistych jednostek, o których chcemy uzyskać informacje.
Stężenia Określają wzajemne ilości substancji wymieszanych ze sobą. Gdy substancje tworzą jednolite fazy to nazywa się je roztworami (np. roztwór cukru.
© Matematyczne modelowanie procesów biotechnologicznych - laboratorium, Studium Magisterskie Wydział Chemiczny Politechniki Wrocławskiej, Kierunek Biotechnologia,
Excel 2007 dla średniozaawansowanych zajęcia z dnia
Wyrażenia Algebraiczne Bibliografia Znak 1Znak 2 Znak 3 Znak 4 Znak 5 Znak 6 Znak 7 Znak 8 Znak 9 Znak 10 Znak 11.
Zmienne losowe Zmienne losowe oznacza się dużymi literami alfabetu łacińskiego, na przykład X, Y, Z. Natomiast wartości jakie one przyjmują odpowiednio.
Rozwiązywanie równań I-go stopnia z jedną niewiadomą
Analiza tendencji centralnej „Człowiek – najlepsza inwestycja”
Równowaga rynkowa w doskonałej konkurencji w krótkim okresie czasu Równowaga rynkowa to jest stan, kiedy przy danej cenie podaż jest równa popytowi. p.
Algorytmy Informatyka Zakres rozszerzony
Lekcja 17 Budowanie wyrażeń algebraicznych Opracowała Joanna Szymańska Konsultacje Bożena Hołownia.
KOMBINATORYKA.
Menu Jednomiany Wyrażenia algebraiczne -definicja Mnożenie i dzielenie sum algebraicznych przez jednomian Mnożenie sum algebraicznych Wzory skróconego.
Instalacja nienadzorowana windows xp Jakub klafta.
Python. Języki Programistyczne Microcode Machine code Assembly Language (symboliczna reprezentacja machine code) Low-level Programming Language (FORTRAN,
Optymalna wielkość produkcji przedsiębiorstwa działającego w doskonałej konkurencji (analiza krótkookresowa) Przypomnijmy założenia modelu doskonałej.
Metody sztucznej inteligencji - Technologie rozmyte i neuronowe 2015/2016 Perceptrony proste nieliniowe i wielowarstwowe © Kazimierz Duzinkiewicz, dr hab.
Usługa ePodatki (MF) Michał Dobrzyński, Departament Informatyki MRPiPS tel
Definiowanie i planowanie zadań typu P 1.  Planowanie zadań typu P  Zadania typu P to zadania unikalne służące zwykle dokonaniu jednorazowej, konkretnej.
 Austriacki fizyk teoretyk,  jeden z twórców mechaniki kwantowej,  laureat nagrody Nobla ("odkrycie nowych, płodnych aspektów teorii atomów i ich zastosowanie"),
PORADNIK WPROWADZANIA AKCJI. OGÓLNIE: Akcja musi zostać utworzona i opublikowana co najmniej tydzień przed jej rozpoczęciem. W opisie muszą znajdować.
O PARADOKSIE BRAESSA Zbigniew Świtalski Paweł Skałecki Wydział Matematyki, Informatyki i Ekonometrii Uniwersytet Zielonogórski Zakopane 2016.
Dziedziczenie, polimorfizm, Interfejsy
Types and Typeclasses Syntax in Functions
Test analizy wariancji dla wielu średnich – klasyfikacja pojedyncza
Programowanie Obiektowe – Wykład 1
W kręgu matematycznych pojęć
Schematy blokowe.
Wyznaczanie miejsc zerowych funkcji
DEFINICJA I ZASTOSOWANIE W JĘZYKU HASKELL
terminologia, skale pomiarowe, przykłady
On-the-Fly Garbage Collection
MATEMATYCZNE MODELOWANIE PROCESÓW BIOTECHNOLOGICZNYCH
Rachunki zdań Tautologiczność funkcji
Logarytmy.
Liczby pierwsze.
Akademia C# - Lab2 Zmienne, instrukcje warunkowe, pętle, debugger,
Rekursje Tak jak w innych językach funkcje mogą odwoływać się same do siebie Możemy regulować głębokość przed stwierdzeniem błędu (MaxRecursion, $RecursionLimit,
Akademia C# lab. 9 Zdarzenia i delegaty.
Programowanie obiektowe
Wstęp do Informatyki - Wykład 3
Elementy analizy matematycznej
Przewodnik Udoskonalanie listy wyników w wyszukiwarce naukowej
Materiały pochodzą z Platformy Edukacyjnej Portalu
Kurs języka C++ – wykład 13 ( )
Języki programowania.
Laboratorium 1 – obsługa wejść i wyjść
Tensor naprężeń Cauchyego
Instrukcje wyboru.
Problem Plecakowy (Problem złodzieja okradającego sklep)
Podstawy informatyki Zygfryd Głowacz.
Strukturalne wzorce projektowe
Pisemne dzielenie liczb naturalnych
MATEMATYKAAKYTAMETAM
To naprawdę bardzo proste!
Zmienne i typy danych w C#
Proste obliczenia w arkuszu kalkulacyjnym
FORMUŁOWANIE HIPOTEZ STATYSTYCZNYCH
Rekurencja Ponieważ w Haskellu nie mamy klasycznych pętli for czy while dlatego w wielu algorytmach musimy używać rekurencji.
Implementacja rekurencji w języku Haskell
Znajdowanie liczb pierwszych w zbiorze
POZNAJEMY PULPIT Opracowanie: mgr Barbara Benisz SP nr 20 w Rybniku
Język C++ Preprocesor Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Język C++ Operatory Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Prawa ruchu ośrodków ciągłych c. d.
Program na dziś Wprowadzenie Logika prezentacji i artykułu
Andrzej Majkowski informatyka + 1.
To naprawdę bardzo proste!
Zapis prezentacji:

Typy i typy klas

Haskell jest statycznym typem języka, tzn Haskell jest statycznym typem języka, tzn., że wszystkie typy i wyrażenia są znane w czasie kompilacji – podnosi to bezpieczeństwo kodu. Jeśli w programie będziesz chciał podzielić zmienną typu bool (prawda albo fałsz) przez liczbę cąłkowitą, program się nie skompiluje.

Nie trzeba podawać typów zmiennych i argumentów funkcji Nie trzeba podawać typów zmiennych i argumentów funkcji. Haskell wywnioskuje to za nas z kontekstu. Jednak pomimo tego, zrozumienie typów jest bardzo ważne.

Typy są pewnego rodzaju etykietami które posiada każde wyrażenie Typy są pewnego rodzaju etykietami które posiada każde wyrażenie. Informuje nas to, do której kategorii pasuje wyrażenie. Przykładowo wartość true należy do typu boolean, a wartość „Hello” jest typu string.

Za pomocą polecenia :t możemy sprawdzić typ wyrażenia. Nazwy wszystkich typów zaczynają się dużą literą. Nawiasy kwadratowe oznaczają, że to lista, w tym przypadku lista

Funkcje również posiadają typy Funkcje również posiadają typy. Podczas pisania własnych funkcji możemy wybrać z góry określony jej typ. Taki zabieg jest zazwyczaj bardzo dobry, z wyjątkiem bardzo krótkich funkcji.

Zapis [Char] -> [Char] oznacza, że będziemy mapować listę znaków Char na inną listę Char. Znaczy to że do funkcji będziemy wprowadzać zmienną typu Char, a jako jej rezultat otrzymamy inną zmienną typu Char. Z racji tego że Char jest synonimem typu String, zapis ten można było by zmienić na String -> String

W powyższym przykładzie nie musieliśmy wpisywać typu, gdyż kompilator sam by go rozpoznał. Jeśli jednak chcieli byśmy stworzyć funkcję z wieloma parametrami, będziemy musieli podać typy dla każdej zmiennej.

Parametry są oddzielone od siebie znakiem -> i nie ma żadnego specjalnego wyróżnienia dla parametrów wejściowych a wyniku funkcji. Wynik jest zawsze na ostatniej pozycji.

Jeżeli piszesz własną funkcję i nie jesteś pewien jaki typ powinieneś zadeklarować, wystarczy pominąć ten krok, a następnie sprawdzić jej typ poleceniem :t. Funkcje również są wyrażeniami, i bez żadnego problemu możemy zastosować polecenie :t.

Int – są to liczby całkowite z przedziału od -2147483648 do 2147483647 Integer – są to również liczby całkowite, z tą jednak różnicą że nie posiadają granicy. Są nieskończone. Float – są to liczby rzeczywiste z pojedynczą precyzją.

Double – liczby rzeczywiste z podwójną precyzją. Bool – zmienna logiczna przyjmująca wartość true albo false. Char – pojedynczy znak. Zapisuje się ją za pomocą pojedynczych ’. String – jest to lista znaków Char. Zapisujemy je zapocą ”.

Zmienne typy gdy zapytamy co pobiera i zwraca funkcja wbudowana head, otrzymamy: Oznacza to, że nazwy typów zaczynają się z wielkiej litery, więc a nie określa typu. Zapis ten oznacza, że funkcja head pobiera listę dowolnych elementów i zwraca jeden z nich (w tym przypadku akurat pierwszy)

Zmienne typy w Haskell-u są tym czym są typy generyczne w innych językach. Funkcje zawierające zmienne typy są nazywane funkcjami polimorficznymi. Zmienne tych funkcji mogą posiadać zmienne o nazwach dłuższych niż jednoliterowe, ale przyjęło się, że używa się właśnie nazw o długości jednej litery.

funkcja fst pobiera dwuelementową krotkę i zwraca element który jest tego samego typu co pierwszy element krotki. Elemeny a i b mogą, ale nie musza być tego samego typu.

W Haskellu operatory ==, +,. , -, / i wiele innych to funkcje W Haskellu operatory ==, +, *, -, / i wiele innych to funkcje. Jeżeli funkcja zawiera jedynie znaki specjalne, domyślnie jest funkcją infiksową. Jeżeli chcemy sprawdzić na jakich typach pracuje musimy przekazać ją do innej funkcji lub uczynić tę funkcję prefiksową czyli musimy nazwę tej funkcji zawrzeć w nawiasach.

Wszystko co występuje przed symbolem => nazywane jest klasą ograniczeń.W przypadku funkcji == możemy to oczytać jako: funkcja równości pobiera dwa elementy tego samego typu należące do klasy obiektów (typeclass) Eq i zwraca typ Bool.

Typeclass Eq udostępnia interfejs do testowania równości Typeclass Eq udostępnia interfejs do testowania równości. Każdy typ dla którego ma sens porównanie dwóch wartości powinien należeć do klasy Eq. Standard języka Haskell wymaga by wszystkie typy i funkcje, z wyjątkiem IO, należały do klasy Eq. Dlatego możemy wykonywać takie porównania:

Typeclass Ord- jest dla typów które mają "kolejność" Typeclass Ord- jest dla typów które mają "kolejność". Funkcje porównujące >, <, >=, <= pobierają dwa argumenty tego samego typu należące do klasy Ord i zwracają obiekt klasy Ordering, tzn. GT, LT lub EQ (greater than, lesser than i equal)Aby typ należał do klasy Ord, musi należeć do klasy Eq.

Typeclass Show- klasa obiektów które mogą być zaprezentowane jako tekst.Najczęściej używaną funkcją należącą do klasy typu Show jest funkcja show. Pobiera ona wartość i wyświetla ją jako tekst.

Typeclass Read Funkcją o działaniu odwrotnym do show jest funkcja read. Pobiera ona tekst i zwraca typ należący do Read.

Czasem jednak są problemy: Funkcja nie wie co zwrócić stąd komunikat. Zazwyczaj kompilator może "wywnioskować" z kontekstu jakiego rodzaju danych oczekujemy, ale jak widać nie zawsze.

Aby pozbyć się błędu musimy zaznaczyć jakiego wyniku oczekujemy:

Typeclass Enum - klasa obiektów do którego należą typy, które mogą być wyliczane. W typie tym dostęp do poprzednika udostępnia funkcja pred, a do następnika funkcja succ. Typy które należą do tej klasy to: (), Bool, Char , Ordering, Int, Integer , Float i Double.

Typeclass Bounded - do tej klasy należą typy mające wartości graniczne Typeclass Bounded - do tej klasy należą typy mające wartości graniczne. Funkcja minBoundzwraca minimalną wartość danego typu,a funkcja maxBoundzwraca maksymalną wartość danego typu. Wszystkie krotki również należą do tej klasy.

Typeclass Num -klasa której członkowie mogą zachowywać się jak liczby. Okazuje się, że funkcja ta akceptuje wszystkie typy należące do klasy Num. Pobiera ona dwie liczby tego samego typu i zwraca liczbę tego samego typu. (5 :: Int) * (6 :: Integer) - wygeneruje błąd, Ale 5 * (6 :: Integer) wykona się ponieważ 5 może działać jak Integer

Typeclass Integral - klasa obiektów należąca do klasy Num. Do Integral należą Int i Integer. Typeclass Floating - typy zmiennoprzecinkowe tzn. Float i Double. Funkcja fromIntegralkonwertuje typy numeryczne na typ Integral. Bardzo użyteczna funkcja jeżeli chcemy używać razem typów zmiennoprzecinkowych z typami całkowitymi.

Składnia funkcji

lucky :: ( Integral a) => a -> String lucky 7 = " LUCKY NUMBER SEVEN !" lucky x= "Sorry , you 're out of luck , pal !„ Pierwsza linia to deklaracja funkcji. Mówi ona, że funkcja pobiera wartość całkowitą i zwraca napis. Ta konstrukcja jest równoważna ze switch znanym z innych języków. Program przechodzi przez wszystkie wszystkie linie i sprawdza zgodność. Ostatnia instrukcja jest odpowiednikiem default czyli jeżeli w poprzednich liniach komputer nie znajdzie dopasowania to zostanie wykonana ostatnia instrukcja. W Haskell każda funkcja musi zwrócić wartość.

Jeżeli chcieli byśmy napisać funkcję, która posiadała by kilka instrukcji, możemy to zrobić następująco: sayMe :: ( Integral a) => a -> String sayMe 1 = " One ! " sayMe 2 = " Two ! " sayMe 3 = " Three !" sayMe 4 = " Four !" sayMe 5 = " Five !" sayMe x = " Not between 1 and 5"

Taki zapis sprawi, że w sytuacji kiedy zostanie wprowadzona liczba z przedziału od 1 do 5, wykona się instrukcja przypisana do danej wartości, a jeżeli zostanie wprowadzona inna liczba, wyświetli się napis „Not between 1 and 5”.

W języku Haskell możemy również wykorzystywać rekurencję W języku Haskell możemy również wykorzystywać rekurencję. Jest ona niezwykle ważna i pomocna. Deklaracja funkcji z użyciem rekurencji wygląda następująco: factorial :: ( Integral a ) => a -> a factorial 0 = 1 factorial n = n * factorial ( n - 1)

Linijka factorial 0 = 1 jest warunkiem końcowym, bez niego funkcja wykonywała by się nieskończenie wiele razy. W przypadku kiedy liczba jest większa od 0 zostanie wczytana liczba n, i następnie zostaje wczytana funkcja z argumentem n-1. Będzie się to powtarzać do momentu aż liczba n będzie równa 0.

Przydatne jest utrzymywanie jednego stylu pisania funkcji Przydatne jest utrzymywanie jednego stylu pisania funkcji. Opisywanie wzorów dla poszczególnych warunków najlepiej pisać na początku, natomiast te ogólne, na jej końcu.

Dopasowywanie wzorów może jednak się nie udać Dopasowywanie wzorów może jednak się nie udać. Jeżeli napiszemy funkcję: charName :: Char -> String charName ’a ’ = " Albert " charName ’b ’ = " Broseph " charName ’c ’ = " Cecil " i nie podamy warunku ogólnego, w sytuacji odwołania się do niepodanego wzoru, otrzymamy błąd.

Dlatego zawsze powinniśmy dodawać opcję dla pozostałych zmiennych, żeby uniknąć występowania błędów w programie.

Dopasowywanie wzorów możemy również stosować z krotkami Dopasowywanie wzorów możemy również stosować z krotkami. Napiszmy funkcję, pobierająco dwa wektory w przestrzeni 2D i dodajmy je do siebie: addVectors :: ( Num a) = > (a , a) -> (a , a) -> (a , a) addVectors (x1 , y1 ) (x2 , y2 ) = ( x1 + x2 , y1 + y2 )

Strażnicy "if" oraz "case" mają swoje odpowiedniki w większości języków programowania. Strażnicy to instrukcja, którą możemy porównać do instrukcji "if" z dodatkowymi warunkami "if else".  Strażnicy to kolejne warunki odpowiadające "if else". Aby określić jaka wartość powinna być zwrócona jeśli żaden z warunków nie zostanie spełniony (odpowiednik "else") definiując ostatniego strażnika zamiast warunku należy wpisać "otherwise".

Funkcja Max Funkcja max przyjmuje dwie wartości i zwraca większą z nich. Strażnicy mogą być zdefiniowani także w jednej linii. Można również samemu zdefiniować funkcję podobną do funkcji max.

Where Klauzula where służy do definiowania wartości i funkcji użytych wewnątrz wyrażeń. Nazwy definiujemy w klauzuli where, gdzie z funkcji są widoczne tylko dla tej funkcji, więc nie musimy się martwić o wystąpienie błędów. Należy jednak umieszczać je w jednej kolumnie, aby Haskell nie pogubił się, czy wszystkie nazwy należą do tego samego bloku funkcji. Jeżeli chcemy używać nazw w wielu innych funkcjach, należy je zdefiniować globalnie.

Można także definiować nazwy tak jak na poniższym przykładzie: Przykład funkcji wyświetlającej inicjały z podanego imienia i nazwiska: Funkcja zwracająca listę par wagi, wysokości i zwracająca listę BMI:

Let it be Bardzo podobne do wiązań where są wiązania let. Wiązania where jest składniowym konstruktem, który pozwala powiązać zmienne na końcu funkcji i cała funkcja może je zobaczyć, w tym wszystkich strażników. Wiązania let pozwalają powiązać zmienne w dowolnym miejscu i wyrażają siebie, ale są bardzo lokalne. Tak jak każdy konstrukt w Haskellu, który jest używany do wiązania wartości z nazwami, wiązania let mogą być wykorzystywane do dopasowania wzorców.W ten sposób możemy zdefiniować funkcję, która daje nam pole powierzchni cylindra w oparciu o jego wysokości i promień:

Składnia jest let <wiązanie> in <wyrażenie> Składnia jest let <wiązanie> in <wyrażenie>. Nazwy, które definiujemy w części let są dostępne dla wyrażenia po części in. Jak widać, możemy również zdefiniować to z wiązaniem where. Zauważmy, że nazwy są ustawione w jednej kolumnie. Różnica polega na tym, że wiązanie let wyrażają siebie. Wiązania where to tylko konstrukcje składniowe.

Mogą one być również stosowane do wprowadzania funkcji w zasięgu lokalnym:

Jeśli chcemy wiązać do kilku zmiennych w linii, to nie możemy wyrównać ich po kolumnach. Dlatego możemy je rozdzielić średnikami

Wiązania let są wyrażeniami są dość lokalne w swoim zakresie, nie mogą być wykorzystywane przez strażników. Niektórzy ludzie wolą where wiązanie ponieważ nazwy pochodzą od funkcji, w której były wykorzystywane. W ten sposób, ciało funkcji jest bliżej nazwy i typowi deklaracji i takie, które jest bardziej czytelne.

Case expressions Wiele języków (C, C++, Java, itp.) Mają składnie case. W case chodzi o wybraniu zmiennej, a następnie wykonaniu bloków kodu dla określonych wartości tej zmiennej, lub może być blok kodu catch-all w przypadku, gdy zmienna ma jakąś wartość, dla której nie utworzono case.

Te dwa fragmenty kodu robią to samo i mogą być stosowane zamiennie:

Składnia wyrażeń jest dość prosta: Expression jest porównywane ze wzorami (pattern). Wzór dopasowania polega na tym, że pierwszy wzór(pattern), który odpowiada expression jest używany. Jeśli przejdzie przez całego case to pojawi się błąd wykonania.

Case są przydatne do dopasowywania wzorców w środku wyrażeń.