ROZDZIAŁ 8: KLASY TYPÓW

Wielkość: px
Rozpocząć pokaz od strony:

Download "ROZDZIAŁ 8: KLASY TYPÓW"

Transkrypt

1 ROZDZIAŁ 8: KLASY TYPÓW

2 Definicja typu Bool: data Bool = False True Słowo kluczowe data oznacza, że definiujemy nowy typ danych. Część przed = określa typ jakim jest bool. Cześć po.. = są to konstruktory wartości, określają one różne wartości jakie może mieć ten typ. jest czytane jako lub ( or) więc znaczy to : typ bool może mieć wartość true lub false. Zarówno nazwa jak i konstruktory wartości tworzą jedną całość. ALGEBRAICZNE TYPY DANYCH

3 data Shape = Circle Float Float Float Rectangle Float Float Float Float Dzięki temu typowi możemy stworzyć koło lub prostokąt Koło może być opisane jako (43.1, 55.0, 10.4) pierwsze 2 liczby to współrzędne środka okręgu 3 liczba to promień. Lepszym rozwiązaniem byłoby nasz typ miał własny kształt. Powiedzmy, że ten kształt by był kołem lub prostokątem Koło posiada konstruktor wartości z 3 polami typu float, więc kiedy piszemy wartość konstruktora możemy dodać parę typów definiując jakie typy będą zawierały. Pierwsze 2 pola są współrzędnymi jego środka, a 3 jego promieniem. Konstruktor wartości prostokąta ma 4 pola typu float. Pierwsze 2 wartości są współrzędnymi jego lewego górnego rogu, a 2 kolejne są długością i wysokością. DEFINICJA WŁASNEGO TYPU SHAPE

4 surface :: Shape -> Float surface ( Circle r) = pi * r ^ 2 surface ( Rectangle x1 y1 x2 y2 ) = ( abs $ x2 - x1 ) * ( abs $ y2 - y1 ) Deklaracja typu mówi nam ze funkcja przyjmuje Shape i zwraca Float. Nie możemy napisać deklaracji typu Circle -> Float ponieważ Circle nie jest typem tylko typem jest Shape. Tak samo nie możemy napisać deklaracji True -> Int. We wzorcu funkcji na pole koła użyliśmy "podkreślników" zamiast 2 pierwszych wartości ponieważ w wyliczaniu pola nie są nam potrzebne. DEFINICJA FUNKCJI Z WŁASNYM TYPEM

5 data Shape = Circle Float Float Float Rectangle Float Float Float Float deriving ( Show ) Użycie deriving show na końcu deklaracji data haskell automatycznie przypisuje nasz typ do typu klasy show ghci > Circle Circle ghci > Rectangle Rectangle DERIVING ( SHOW )

6 Lista kół o tym samym środku z różnymi promieniami ghci > map ( Circle 10 20) [4,5,6,6] [ Circle , Circle , Circle , Circle ] MAPOWANIE KONSTRUKTORÓW WARTOŚCI

7 data Point = Point Float Float deriving ( Show ) data Shape = Circle Point Float Rectangle Point Point deriving ( Show ) Podczas definiowania Point użyliśmy tej samej nazwy dla typu danych i konstruktora wartości nie ma specjalnego znaczenia jednakże powszechnym jest używanie tej samej nazwy jaką ma typ. Jeżeli jest tylko jeden konstruktor wartości. Od teraz Circle ma 2 pola jedna jest typu Point a 2-gi typu Float. Teraz nasze kształty są łatwiejsze w rozumieniu. Przedefiniowanie funkcji surface: surface :: Shape -> Float surface ( Circle _ r) = pi * r ^ 2 surface ( Rectangle ( Point x1 y1 ) ( Point x2 y2 )) = ( abs $ x2 - x1 ) * ( abs $ y2- y1 ) Jedyną rzeczą którą musieliśmy zmienić był wzorzec. Dla koła zastąpiliśmy 2 podkreślniki jednym ponieważ nie potrzebujemy wartości zmiennej typu point. ghci > surface ( Rectangle ( Point 0 0) ( Point )) ghci > surface ( Circle ( Point 0 0) 24) SHAPE Z POINT-EM

8 nudge :: Shape -> Float -> Float -> Shape nudge ( Circle ( Point x y) r) a b = Circle ( Point ( x+a) (y+ b )) r nudge ( Rectangle ( Point x1 y1 ) ( Point x2 y2 )) a b = Rectangle ( Point ( x1 +a) ( y1 +b )) ( Point ( x2 + a) ( y2 +b )) Wywołanie: ghci > nudge ( Circle ( Point 34 34) 10) 5 10 PRZESUNIĘCIE FIGURY WZGLĘDEM OSI X,Y

9 data Person = Person String String Int Float String String deriving ( Show ) Aby uzyskać poszczególne informacje (tj. tylko imię, nazwisko) należy zdefiniować następujące funkcje: firstname :: Person -> String firstname ( Person firstname _) = firstname lastname :: Person -> String lastname ( Person _ lastname ) = lastname age :: Person ->Int age ( Person age _) = age height :: Person ->Float height ( Person _ height ) = height phonenumber :: Person -> String phonenumber ( Person number _ ) = number flavor :: Person -> String flavor ( Person _ flavor ) = flavor SKŁADNIA REKORDÓW

10 data Person = Person { firstname :: String, lastname :: String, age :: Int, height :: Float, phonenumber :: String, flavor :: String } deriving ( Show ) Zamiast określania typów pól jeden po drugim oddzielonymi spacjami, używamy klamr. Najpierw piszemy nazwę pola np. firstname a następnie dodajemy :: (czterokropek) i określamy typ pola. Dzięki temu tworzymy jednocześnie odnośniki do poszczególnych pól. SKŁADNIA REKORDÓW

11 Typ konstruktorów mogą pobierać typy jako parametry do tworzenia nowych typów data Maybe a = Nothing Just a Mamy tutaj a jako typ parametru. I właśnie dlatego wywołujemy funkcję Maybe. Ten typ może nam zwrócić Nothing lub typ wejściowy. Aby było to prawdziwe potrzebne są zapełnione typy parametrowe. ghci > Just " Haha " Just " Haha " ghci > Just 84 Just 84 ghci > :t Just " Haha " Just " Haha " :: Maybe [ Char ] ghci > :t Just 84 Just 84 :: ( Num t) => Maybe t ghci > :t Nothing Nothing :: Maybe a ghci > Just 10 :: Maybe Double Just 10.0 TYP PARAMETROWY

12 Typy parametrowe są użyteczne ponieważ możemy zrobić różne typy w zależności od rodzaju typów jakie chcemy by były zawarte w naszym typie danych. Kiedy piszemy : " :t just " hahah" kompilator interpretuje że jest to Maybe z listą Charów [Char], ponieważ widzi że otrzymał String/[Char] na wejściu. Typ maybe a może określić podobny do typu maybe int jeżeli jest 5 to wtedy przyjmuje inta lub double. Podobnie jeżeli lista jest pusta to wtedy jest [a].pusta lista moze działać jak listy czegokolwiek dlatego możemy zrobić [1,2,3] ++ [] and ["ha","ha","ha"] ++ []. Użycie typu parametrowego jest bardzo korzystne jeśli używamy go sensownie. Zazwyczaj używamy kiedy nasz typ danych będzie niezależne od typu wartości, wtedy wartości trzyma w środku. Podobnie jak typ " maybe a "

13 JEŻELI NASZ TYP DZIAŁA JAK PEWNEGO RODZAJU POLE ( PUDEŁKO) WARTO Z NIEJ KORZYSTAĆ. MOŻEMY ZMIENIĆ NASZ CAR DATA: data Car = Car { company :: String, model :: String, year :: Int } deriving ( Show ) tellcar :: Car -> String tellcar ( Car { company = c, model = m, year = y }) = " This " ++ c ++ " " ++ m ++ " was made in " ++ show y ghci > let stang = Car { company =" Ford ", model =" Mustang ", year =1967} ghci > tellcar stang " This Ford Mustang was made in 1967 " data Car a b c = Car { company :: a, model :: b, year :: c } deriving ( Show ) tellcar :: ( Show a) => Car String String a -> String tellcar ( Car { company = c, model = m, year = y }) = " This " ++ c ++ " " ++ m ++ " was made in " ++ show y

14 ghci > tellcar ( Car " Ford " " Mustang " 1967) " This Ford Mustang was made in 1967 " ghci > tellcar ( Car " Ford " " Mustang " " nineteen sixty seven ") " This Ford Mustang was made in \" nineteen sixty seven \" " ghci > :t Car " Ford " " Mustang " 1967 Car " Ford " " Mustang " 1967 :: ( Num t) = > Car [ Char ] [ Char ] t ghci > :t Car " Ford " " Mustang " " nineteen sixty seven " Car " Ford " " Mustang " " nineteen sixty seven " :: Car [ Char ] [ Char ] [ Char ]

15 KLASY TYPÓW (DOŁĄCZANIE INSTANCJI) Klasy typów (typeclass) to rodzaj interfejsu, który określa pewne zachowania. Przykład: Typ int znajduje się w typie klasy eq ponieważ definiuje zachowanie elementów które mogą zostać utożsamione ze sobą. Ponieważ można porównywać liczby całkowite int jest on częścią typu klasy eq. Najczęściej wykorzystywaną funkcją w eq jest interfejs porównania == i /=. Jeśli typ jest częścią typu klasy eq, możemy użyć funkcji == z wartościami tego typu. Dlatego wyrażenia, takie jak 4 == 4 i "foo" / = "bar" może porównać te wartości.

16 Wspomnijmy również o tym, że są one często mylone z klasami w językach takich jak Java, Python, C++ i tym podobnych, co czyni wielu ludzi. W tych językach klasy są projektem z których tworzymy obiekty, one zaś zawierają stany i mogą robić kilka czynności. Klasy typów są bardziej jak interfejsy. Nie tworzymy danych z typów klas. Zamiast tego, musimy najpierw zrobić nasz typ danych, a następnie zastanowić się jak możemy go wykorzystać. Jeśli może działać jak coś, co można porównać, robimy to w instancji typu klasy Eq. Jeśli może działać jak coś co można posortować, robimy to w instancji typu klasy Ord.

17 Możemy ręcznie dodawać nasze typy instancji po przez realizacje funkcji zdefiniowanych przez typy klas. Haskell może automatycznie wykonać nasz typ instancji w następujących typach klas: eq, Ord, Enum,Bounded, Show, Read. Haskell może "podczepić" zachowanie naszych typów w tych kontekstach, jeśli użyjemy słów kluczowych.

18 data Person = Person { firstname :: String, lastname :: String, age :: Int } W powyższym kodzie opisaliśmy osobę. Załóżmy, że nie ma dwóch osób o tym samym imieniu, nazwisku oraz wieku. Teraz jeśli mamy rekord dla dwóch osób, czy ma on sens jeśli reprezentuję tę samą osobę? Pewnie, że nie. Możemy starać się je porównać i zobaczyć czy są one identyczne, czy nie. Wtedy ma to sens i dlatego jest częścią klasy typu eq.

19 Gdy pobierzemy z eq instancję dla typu, a następnie spróbujemy porównać dwie wartości tego typu z == lub/=, Haskell spostrzeże że elementy nie pasują do siebie, a następnie sprawdzi, wszystkie dane zawarte wewnątrz testując każdą parę pól z ==. Jest tylko jeden haczyk, typy we wszystkich dziedzinach muszą również być częścią typu klasy eq. Ponieważ zarówno string i int są, więc jest w porządku. data Person = Person { firstname :: String, lastname :: String, age :: Int } deriving (Eq)

20 SPRAWDŹMY NASZE INSTANCJE EQ: ghci > let miked = Person { firstname = " Michael ", lastname = " Diamond ", age = 43} ghci > let adrock = Person { firstname = " Adam ", lastname = " Horovitz ", age = 41} ghci > let mca = Person { firstname = " Adam ", lastname = " Yauch ", age = 44} ghci > mca == adrock False ghci > miked == adrock False ghci > miked == miked True ghci > miked == Person { firstname = " Michael ", lastname = " Diamond ", age = 43} True

21 Oczywiście person jest teraz w eq, możemy użyć go do wszystkich funkcji które mają klasy ograniczone w eq, takich jak elem. ghci > let beastieboys = [mca, adrock, miked ] ghci > miked `elem ` beastieboys True

22 Klasy typów show i Read, są elementami które mogą być konwertowane do lub z ciągów znaków. Podobnie jak w eq, jeśli konstruktory mają pola, ich typ mógłby być częścią show lub read, jeśli chcemy aby nasz typ instancji zawierał się w nich. Uczyńmy nasz typ danych person częścią show i read. data Person = Person { firstname :: String, lastname :: String, age :: Int } deriving (Eq, Show, Read )

23 ghci > let miked = Person { firstname = " Michael ", lastname = " Diamond ", age =43} ghci > miked Person { firstname = " Michael ", lastname = " Diamond ", age = 43} ghci > " miked is: " ++ show miked " miked is: Person { firstname = \" Michael \", lastname = \" Diamond \", age = 43} " Teraz możemy wypisać osoby na terminalu:

24 Read jest odwrotnością klasy typu Show. Show jest konwersją wartości typu string. Read jest konwersją stringów do wartości naszego typu. Pamiętajmy jednak, gdy używamy funkcji read, musimy użyć adnotacji wyraźnego typu by powiedzieć Haskelowi jaki typ chcemy uzyskać w wyniku. Jeśli nie poprosimy o typ w wyniku, Haskell nie będzie wiedział jaki typ chcemy uzyskać.

25 ghci > read " Person { firstname =\" Michael \", lastname =\" Diamond \", age = 43}":: Person Person { firstname = " Michael ", lastname = " Diamond ", age = 43} Jeśli użyjemy wyniku naszego read to Haskell będzie mógł wywnioskować, że powinien ją przeczytać jako person, wtedy nie musimy używać typu adnotacji ghci > read " Person { firstname =\" Michael \", lastname =\" Diamond \", age = 43}"== miked True Możemy również z read odczytać parametry typów, lecz pierw musimy je nimi wypełnić. Więc nie możemy napisać read Just 't' ::maybe a, ale możemy zapisać read Just t ::Maybe Char.

26 data Bool = False True deriving (Ord) Ponieważ konstruktor false jest pierwszy a konstruktor true jest określony po nim, możemy rozważyć true jako wartość większą niż wartość false. ghci > True `compare ` False GT ghci > True > False True ghci > True < False False

27 W typie danych Maybe konstruktor wartości Nothing określony jest przed wartością konstruktora Just, więc wartość Nothing jest zawsze mniejsze ni ż wartość Just, nawet jeśli wynosi ona minus miliard bilionów. Ale jeśli porównać dwie wartości Just, to należy porównać ich wnętrze. ghci > Nothing < Just 100 True ghci > Nothing > Just ( ) False ghci > Just 3 `compare ` Just 2 GT ghci > Just 100 > Just 50 True

28 Lecz nie możemy robić czegoś takiego: Just (*3)>Just(*2), ponieważ (*3) i (*2) są funkcjami które nie są instancjami w Ord. Możemy za to łatwo korzystać z algebraicznych typów danych do wyliczeń i klasy typów Enum oraz bounded pomoże nam z tym. Rozważmy następujący typ danych: data Day = Monday Tuesday Wednesday Thursday Friday Saturday Sunday

29 Ponieważ wszystkie konstruktory wartości są puste( nie podejmują parametrów takich jak pola), możemy zrobić z niego część typu klasy Enum. Enum jest dla wartości, które posiadają poprzedników i następców. Możemy również zrobić to w części klasie typu Bounded,który jest dla typów, które mają najniższą możliwą wartość i najwyższą możliwą wartość. A skoro już przy tym jesteśmy, sprawdźmy wystąpienie wszystkich typów klas i zobaczmy, co możemy z nimi zrobić:

30 data Day = Monday Tuesday Wednesday Thursday Friday Saturday Sunday deriving (Eq, Ord, Show, Read, Bounded, Enum ) Ponieważ jest to część klas typów Show I Read, możemy przekonwertować wartość tego typu jako string. ghci > Wednesday Wednesday ghci > show Wednesday " Wednesday " ghci > read " Saturday " :: Day Saturday

31 Ponieważ jest to część klas typów eq i Ord, możemy je porównać (porównać dni): ghci > Saturday == Sunday False ghci > Saturday == Saturday True ghci > Saturday > Friday True ghci > Monday `compare ` Wednesday LT

32 Jest to także część Bounded, więc możemy dodać najniższy i najwyższy dzień: ghci > minbound :: Day Monday ghci > maxbound :: Day Sunday Jest to również instancja Enum. Możemy dostać poprzednie i następne dni. I możemy zrobić listy zakresów od nich

33 ghci > succ Monday Tuesday ghci > pred Saturday Friday ghci > [ Thursday.. Sunday ] [ Thursday, Friday, Saturday, Sunday ] ghci > [ minbound.. maxbound ] :: [Day] [ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday ]

34 Wcześniej wspominaliśmy że podczas pisania typów [Char] i String typy te są sobie równoważne i są wymienne. Oznacza to że są zaimplementowane w typach synonimowych. Typy synonimowe tak naprawdę nie robi nic w sobie, jedynie daje pewne typy różnych nazw, więc nadaje sens komuś kto czyta nasz kod i dokumentacje. Tak więc standardowa biblioteka definiuje String jako synonim z [Char]. type String = [ Char ] Wprowadziliśmy słowo kluczowe type. Niektóre Słowa kluczowe mogą być mylące, gdyż aktualnie nie robimy niczego nowego ( zrobiliśmy to z kluczowych danych), właśnie wykonaliśmy synonim z już istniejących typów. Jeżeli zrobimy funkcje która konwertuje string do dużych liter i nazwiemy ją toupperstring, możemy nadać mu deklaracje typu toupperstring :: [Char] -> [Char] lub toupperstring :: String -> String. Obydwie deklaracje są zasadniczo takie same, jedynie ostatni zapis jest łatwiejszy do czytania. 8.5 TYPY SYNONIMOWE

35 Kiedy mamy doczynienia z modułem Data. Map, najpierw zaprezentujemy książkę telefoniczną z listy asocjacyjnej następnie przekształciliśmy ją w map. Lista asocjacyjna to lista stworzona z par kluczy-wartości. Nasza wcześniejsza książka wyglądała następująco: phonebook :: [( String, String )] phonebook = [( " betty "," " ),(" bonnie "," "),(" patsy "," "),(" lucille "," " ),(" wendy "," "),(" penny "," ") ]

36 Jak widzimy typ phonebook jest [(String,String)]. Mówi nam to że jest to lista asocjacyjna która mapuje ze stringa na stringa, lecz nic więcej. Zróbmy typ synonimowy który przekazuje więcej informacji w deklaracji typu. type PhoneBook = [( String, String )] Teraz deklaracja typu z twojej książki telefonicznej może być phonebook :: PhoneBook. Zróbmy typ synonimowy także dla String. type PhoneNumber = String type Name = String type PhoneBook = [( Name, PhoneNumber )]

37 Nadawanie String typów synonimowych jest czymś co programiści Haskella chcą przekazać więcej informacji o stingach do funkcji które powinny być użyte jak i co one reprezentują. Teraz kiedy zaimplementujemy funkcje która pobiera nazwę i nr to widzi czy taka kombinacja naszej nazwy i nr jest w naszej książce telefonicznej. Możemy nadać bardziej opisową deklaracje typu: inphonebook :: Name -> PhoneNumber -> PhoneBook -> Bool inphonebook name pnumber pbook = ( name, pnumber ) `elem ` pbook Jeżeli postanowilibyśmy nie używać typów synonimowych, nasza funkcja wyglądała by: String -> String -> [(String,String)] -> Bool. W tym wypadku, deklaracja typu korzystająca z typów synonimowych jest łatwiejsza do zrozumienia. Jednak nie powinno się go nadużywać. Wprowadzamy typy synonimowe gdy opisujemy niektóre istniejące reprezentacje typów w naszych funkcjach (by ulepszyć dokumentację) lub kiedy coś ma długi typ który jest często powtarzany np: ([(String,String)]).

38 Typy synonimów mogą być również parametryzowane. Jeżeli chcemy aby typ który reprezentuje typ listy asocjacyjnej był nadal ogólny to możemy używać jakichkolwiek typów jako kluczy i wartości. Możemy zrobić to tak: type AssocList k v = [(k,v )] Gdybyśmy chcieli typ który reprezentuje mapę (map) (z Data.Map) z liczb całkowitych możemy to zrobić tak: lub : type IntMap v = Map Int v type IntMap = Map Int Tak czy inaczej konstruktor typu IntMap bierze jeden parametr, który będzie wskazywać na liczby całkowite

39 Innym fajnym typem danych który przyjmuje 2 typy jako swoje parametry jest typeither a b. data Either a b = Left a Right b deriving (Eq, Ord, Read, Show ) Posiada dwa konstuktory wartości. Jeżeli Left jest użyty, to jego zawartością jest a i jeżeli Right jest użyty to jego zawartością jest b. Więc możemy użyć tego typu w enkapsulacji wartości z jednego typu lub innego i gdy mamy wartość typu Either a b, zazwyczaj wzór dopasowuje zarówno Left i Right, wtedy bazujemy na jednym z nich: ghci > Right 20 Right 20 ghci > Left " w00t " Left " w00t " ghci > :t Right 'a ' Right 'a ' :: Either a Char ghci > :t Left True Left True :: Either Bool b

40 Do tej pory widzieliśmy Maybe a używane do reprezentacji wyników obliczeń które mogą być zarówno poprawne lub nie. Lecz niekiedy, Maybe jest niewystarczająco dobre gdyż Nothing nie przekazuje wielu informacji kiedy mu się nie powiedzie. Jest dobry tylko dla funkcji, które mogą wyłącznie w jeden sposób zawieść lub nie interesuje nas w jaki sposób funkcja zawiodła. Data.Map wyszukuje błędy tylko wtedy kiedy klucz którego szukaliśmy nie był w mapie, wtedy wiemy co się dokładnie stało. Jednak kiedy jesteśmy zainteresowani jak funkcja się popsuła lub dlaczego to zazwyczaj używamy typu wynikowego Either a b, gdzie a jest jakiegoś typu, który może coś powiedzieć o możliwej awarii i b jest typu udanych obliczeń. Stąd błędy używają Left wartości konstruktorów natomiast wyniki używają Right.

41 Przykład: w szkole średniej są szafki tak, że uczniowie mają miejsce by umięsić swoje plakaty GUNS'N'ROSES. Każda szafka posiada kod. Kiedy uczeń chce nową szafkę mówi nadzorcy którą szafkę chce, a ten daje mu kod, ale jeśli ktoś używa tą szafkę, nie może powiedzieć mu kodu do szafki i uczeń musi wybrać inną. Użyjemy map z Data.Map do reprezentowania szafek. To będzie mapa z numerami szafek, z parą czy szafka jest używana czy nie i kod. import qualified Data. Map as Map data LockerState = Taken Free deriving ( Show, Eq ) type Code = String type LockerMap = Map. Map Int ( LockerState, Code )

42 Wprowadzamy nowy typ danych do reprezentowania czy szafka jest wolna czy zajęta i ustawiamy typ synonimowy dla kodu szafki. Robimy również typ synonimowy dla typu który mapuje z intiger do par stanu szafek i ich kodu. Teraz przejdźmy do funkcji, która wyszukuje kod w mapie szafek. Zamierzamy użyć typu Either String Code do reprezentowania naszego wyniku, ponieważ nasze wyszukiwanie może się nie powieść w 2 przypadkach kiedy szafka mogą być zajęte, w tym przypadku nie może powiedzieć kodu lub kiedy numer szafki może nie istnieć. Jeśli wyszukiwanie się nie powiedzie, użyjemy stringa by powiedzieć co się stało. lockerlookup :: Int -> LockerMap -> Either String Code lockerlookup lockernumber map = case Map. lookup lockernumber map of Nothing -> Left $ " Locker number " ++ show lockernumber ++ " doesn 't exist!" Just ( state, code ) -> if state /= Taken then Right code else Left $ " Locker " ++ show lockernumber ++ " is already taken!"

43 Robimy normalne wyszukiwanie na mapie. Jeżeli otrzymamy Nothing, zwraca wartość typu Left String, mówiąc że szafka w ogóle nie istnieje. Jeśli znajdzie ją wtedy wykonuje kolejne sprawdzenie, czy szafka jest wolna. Jeżeli nie jest zwraca Left mówiąc jest niedostępna. Jeżeli nie jest wtedy zwraca wartość typu Right Code w którym dajemy studentowi prawidłowy kod do szafki. To aktualny Right String, lecz wprowadziliśmy typ synonimowy do wprowadzenia pewnej dodatkowej dokumentacji do deklaracji typu. Przykład map: lockers :: LockerMap lockers = Map. fromlist [(100,( Taken," ZD39I " )),(101,( Free," JAH3I " )),(103,( Free," IQSA9 " )),(105,( Free," QOTSA " )),(109,( Taken," 893 JJ " )),(110,( Taken," " ))

44 A oto kod szafki: ghci > lockerlookup 101 lockers Right " JAH3I " ghci > lockerlookup 100 lockers Left " Locker 100 is already taken!" ghci > lockerlookup 102 lockers Left " Locker number 102 doesn 't exist!" ghci > lockerlookup 110 lockers Left " Locker 110 is already taken!" ghci > lockerlookup 105 lockers Right " QOTSA " Moglibyśmy skorzystać z Maybe do prezentacji wyników lecz wtedy nie wiedzielibyśmy dlaczego nie możemy dostać kodu, a w tym przypadku dostajemy informację na temat problemu;)

45 REKURENCYJNE STRUKTURY DANYCH

46 Jak widzieliśmy konstruktor w algebraicznym typie danych może mieć kilka (lub wcale) pól i każde pole musi być jakimś konkretnym typem. Mając to na uwadze, możemy mieć typy których konstruktory mają pola które są tego samego typu. Możemy stworzyć rekurencyjne typy danych gdzie jedna wartość pewnego typu zawiera wartość danego typu, które zawierają więcej wartości tego samego typu i tak dalej. Przeanalizujmy listę: [5]. Jest to po prostu cukier syntaktyczny dla 5:[].Po lewej stronie : jest wartość a po prawej jest lista. W tym przypadku jest ona pustą listą. Teraz co z listą [4,5]? Więc "pocukrowane" to 4:(5:[]). Patrząc na pierwsze :, widzimy że ma również element z lewej strony i listę (:5) z prawej strony. Identycznie odnosi się do listy jak 3:(4:(5:6:[])), które mogą być napisane podobnie bądź 3:4:5:6[] (gdyż : jest prawo-asocjacyjne) lub [3,4,5,6]. Można powiedzieć że lista może być pustą listą lub może być elementem połączonym razem z : z inną listą (które mogą być pustymi listami lub nie). Użyjmy algebraicznych typów danych do implementacji nasza lista to: data List a = Empty Cons a ( List a ) deriving ( Show, Read, Eq, Ord ) 8.6 REKURENCYJNE STRUKTURY DANYCH

47 To wygląda jak definicja naszej listy z wcześniejszego paragrafu. To jest pusta lista lub połączenie głowy z jakąś wartością i listy. data List a = Empty Cons { listhead :: a, listtail :: List a } deriving ( Show, Read, Eq, Ord ) Może nas zmieszać tutaj Cons konstruktora. Cons jest kolejnym słowem dla :. Widzisz w listach : jest faktycznym konstruktorem przyjmującym wartości oraz inną listę i zwracającym listę. Możemy już korzystać z naszej nowej listy typów! Innymi słowy ma dwa pola. Jedno pole jest typu a i kolejne jest typu [a]. ghci>empty Empty ghci> 5 ` Cons ` Empty Cons 5 Empty ghci> 4 ` Cons ` (5 `Cons ` Empty ) Cons 4 ( Cons 5 Empty ) ghci> 3 ` Cons ` (4 `Cons ` (5 `Cons ` Empty )) Cons 3 ( Cons 4 ( Cons 5 Empty )) Funkcja infix-owa (wrostkowa) Wywołaliśmy nasz konstruktor Cons który jest wywołany infixowo więc możesz zobaczyć co do czego jest podobne :. Empty podobne do [] i 4 Cons (5 `Cons` Empty)podobne do 4:(5:[]).

48 Możemy zdefiniować że funkcje będą automatycznie infixowane tworząc je zawierające jedynie znaki specjalne. Możemy tak samo zrobić z konstruktorami ponieważ są one tylko funkcjami i zwracają jakiś typ danych. infixr 5 : -: data List a = Empty a : -: ( List a) deriving ( Show, Read, Eq, Ord ) Po pierwsze zauważyliśmy nową konstrukcje składniową oraz deklaracje stałości. Kiedy definiujemy funkcje jako operatory możemy tego użyć by nadać im stałość (ale nie musimy tego robić). Stałość ustala jak mocno operator jest przypisany i czy jest powiązany lewostronnie czy prawostronnie. Dla przykładu stałość dla * to infixl 7 *i stałość + to infixl 6. Oznacza to że oba operatory są powiązane lewostronnie (4 * 3 * 2 to to samo co (4 * 3) * 2) ale * powiązuje mocniej niż + bo ma większą stałość więc 5 * 4 + 3to(5 * 4) + 3. W innym przypadku możemy napisać :-: (List a) zamiast Cons a (List a). Teraz więc możemy zapisywać nasze listy w sposób następujący ghci> 3 : -: 4 : -: 5 : -: Empty (: -:) 3 ((: -:) 4 ((: -:) 5 Empty )) ghci>let a = 3 : -: 4 : -: 5 : -: Empty ghci> 100 : -: a (: -:) 100 ((: -:) 3 ((: -:) 4 ((: -:) 5 Empty ))) Kiedy nasz typ wywodzi się od Show haskell nadal wyświetli go tak jak by był konstruktorem funkcji prefiksowej stąd nawiasy na zewnątrz operatora (4 + 3 to to samo co (+) 4 3).

49 Zróbmy funkcje która doda dwie z naszych list razem. W ten sposób ++ definiujemy dla normalnych list: Nazwą funkcji będzie.++. I zobaczmy jak to działa infixr 5 ++ (++) :: [ a] -> [a] -> [a] [] ++ ys = ys (x: xs ) ++ ys = x : ( xs ++ ys ) infixr 5.++ (.++) :: List a -> List a -> List a Empty.++ ys = ys (x : -: xs ).++ ys = x : -: ( xs.++ ys ) ghci>let a = 3 : -: 4 : -: 5 : -: Empty ghci>let b = 6 : -: 7 : -: Empty ghci> a.++ b (: -:) 3 ((: -:) 4 ((: -:) 5 ((: -:) 6 ((: -:) 7 Empty ))))

50 Teraz przejdźmy do implementacji drzewa wyszukiwania binarnego. Definicja drzewa binarnego: każdy punkty elementu posiada dwa elementy jednego z lewej a drugiego z prawej. Element po lewej jest mniejszy od elementu po prawej. Każdy z tych elementów może również wskazywać na dwa elementy (lub jeden, lub brak).w efekcie, każdy element ma maksymalnie dwa poddrzewa. Wszystkie elementy w lewym poddrzewie powiedzmy 5 będą mniejsze od 5. Elementy w prawym poddrzewie będą większe. Więc jeśli musimy znaleźć 8 jeśli jest w naszym drzewie chcemy zacząć od 5 i dlatego że 8 jest większa od 5 to pójdziemy w prawo. Jesteśmy teraz na 7 i dlatego że 8 jest większa od 7 więc pójdziemy znów w prawo. I znaleźliśmy nasz element w trzech ruchach. Teraz jeżeli to była normalna lista (lub drzewo, ale niezrównoważone), zajęło by nam to siedem ruchów zamiast trzech aby zobaczyć czy istnieje 8. Zestawy i mapy z Data.Set i Data.Map są zaimplementowane z wykorzystaniem drzewa, jedynie zamiast zwykłego przeszukiwania drzewa binarnego, używają zrównoważonego przeszukiwania drzewa binarnego, które są zrównoważone. Ale teraz trzeba po prostu zaimplementować normalne binarne drzewo przeszukiwań. Drzewo jest albo pustym drzewem lub drzewem które zawiera elementy o pewnej wartości i dwa poddrzewa. Brzmi jak idealne dopasowanie do typu danych algebraicznych! data Tree a = EmptyTree Node a ( Tree a) ( Tree a) deriving ( Show, Read, Eq )

51 W języku tj. C robimy to modyfikując wskaźnik i wartość wewnątrz drzewa. W Haskellu nie możemy tak naprawdę modyfikować naszego drzewa, więc musimy zrobić nowe subdrzewo za każdym razem gdy decydujemy się iść w lewo lub w prawo, a na koniec wstawiania funkcja zwraca kompletnie nowe drzewo gdyż Haskell naprawdę nie ma pojęcia o wskaźnikach. Stąd typ naszej funkcji wstawiania będzie a ->Tree a - >Tree a. Pobiera element i drzewo i zwraca nowe drzewo które ma ten element w sobie. Więc mamy 2 funkcje. Jedna jest funkcją do tworzenia drzewa singleton (drzewo z jednym węzłem) i funkcja do wstawiania elementu do drzewa. singleton :: a ->Tree a singleton x = Node x EmptyTreeEmptyTree treeinsert :: ( Ord a ) = > a ->Tree a ->Tree a treeinsert x EmptyTree = singleton x treeinsert x ( Node a leftright ) x == a = Node x leftright x < a = Node a ( treeinsert x left ) right x > a = Node a left ( treeinsert x right )

52 Funkcja singleton jest jedynie skrótem do tworzenia węzła, który coś zawiera i dwa puste sub-drzewa. W funkcji wstawiania najpierw mamy stany krawędzie jako wzorzec. Jeżeli doszliśmy do pustego sub-drzewa, to oznacza że jesteśmy tam gdzie chcemy i zamiast pustego drzewa stawiamy drzewo singleton z naszego elementu. Jeżeli nie wstawiamy do pustego drzewa to musimy sprawdzić kilka rzeczy. Po pierwsze jeżeli mamy do włożenia element równy elementowi głównemu po prostu zwróci drzewo takie same. Jeśli jest mniejszy zwróci drzewo które ma taką samą główną wartość. Ten sam korzeń prawego subdrzewa ale zamiast jego lewego sub-drzewa wstawi drzewo które ma wartość wstawioną do niego. Tak samo (lecz w drugą stronę) idzie gdy wartość jest większa od elementu głównego. treeelem :: ( Ord a) => a ->Tree a ->Bool treeelem x EmptyTree = False treeelem x ( Node a leftright ) x == a = True x < a = treeelem x left x > a = treeelem x right Wszystko co musimy zrobić to napisać w poprzednim akapicie w kodzie. Zamiast ręcznej budowy jednego (choć możemy) użyjemy konkretnie do budowy drzewa z listy.

53 Wypełnijmy nasze drzewo: ghci>letnums = [8,6,4,1,7,3,5] ghci>letnumstree = foldrtreeinsertemptytreenums ghci>numstree Node 5 ( Node 3 ( Node 1 EmptyTreeEmptyTree ) ( Node 4 EmptyTreeEmptyTree )) ( Node 7 ( Node 6 EmptyTreeEmptyTree ) ( Node 8 EmptyTreeEmptyTree )) W tym foldr, treeinsert była funkcją składania (przyjmuje drzewo i element listy i tworzy nowe drzewo) i EmptyTree zaczyna akumulować. Nums, była listą składaną. Kiedy drukujemy nasze drzewo do konsoli to nie jest to zbytnio czytelne, ale jeśli spróbujemy możemy zrozumieć jego strukturę. Widzimy że węzeł główny jest 5 i ma dwa sub-drzewa jedno zawiera węzeł 3 i inny 7, itp. ghci> 8 ` treeelem ` numstree True ghci> 100 ` treeelem ` numstree False ghci> 1 ` treeelem ` numstree True ghci> 10 ` treeelem ` numstree False

54 Klasy typów definiują pewne zachowanie (takie jak porównywanie, zliczanie) i typy mogą odnosić się do tworzenia instancji tych klas typów. W przypadku klasy typów zarchiwizowanych przy definicji funkcji lub tylko zadeklarowane typy które następnie wdrażamy. Więc kiedy mówimy że typy są instancją typów klas mamy na myśli że możemy użyć funkcje zdefiniowanych klas typów z typem. KLASY TYPÓW 102

55 class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) Po pierwsze kiedy piszemy class Eq a where, to oznacza definicje nowego typu klas i nazywa się Eq. A jest typem zmiennej i oznacza że będzie odgrywać rolę typu wkrótce robi instancję Eq. Następnie definiujemy kilka funkcji. W każdym razie wdrażamy ciało funkcji dla funkcji Eq tylko określiliśmy je pod względem wzajemnej rekursji. Powiedzieliśmy że dwie instancje Eq są równe jeżeli nie są one różne i są różne jeżeli nie są równe. Jeżeli mamy mówić class Eq a where i następnie określić typ deklaracji w tej klasie (==) :: a -> -a -> Bool,wtedy gdy badamy typ tej funkcji później będzie miał typ (Eq a) =>a -> a -> Bool.

56 data TrafficLight = Red Yellow Green Jeśli zdefiniowaliśmy TrafficLight. Zauważmy że nie czerpią z żadnej instancji klasy. To dlatego że mamy zamiar napisać kilka instancji po kolei, nawet jeżeli możemy czerpać z takich typów jak Eq i Show. Instancję dla Eq: instance Eq TrafficLight where Red == Red = True Green == Green = True Yellow == Yellow = True _ == _ = False Zrobiliśmy to za pomocą słowa kluczowego instance. Więc class jest dla definiowania nowej klasy typu i instance do tworzenia rodzaj instancji w typie klasy. == jest zdefiniowane w kategoriach /= i odwrotnie w deklaracji class. Aby spełnić minimalną pełną definicje dla Eq musimy nadpisać == lub /=.

57 Aby spełnić minimalną kompletną definicje dla Show po prostu musimy zaimplementować funkcje Show która przyjmuje wartość i zmienia go na stringa. instance Show TrafficLight where show Red = " Red light " show Yellow = " Yellow light " show Green = " Green light " ghci > Red == Red True ghci > Red == Yellow False ghci > Red `elem ` [ Red, Yellow, Green ] True ghci > [ Red, Yellow, Green ] [ Red light, Yellow light, Green light ]

58 Mogliśmy po prostu zaczerpnąć Eq i miałaby taki sam efekt. Jednak zaczerpnięcie Show musiałby tylko bezpośrednio przetłumaczyć wartość konstruktorów do stringa. Ale jeśli chcemy światło czerwone "Red light", wtedy musimy sporządzić deklarację instancji ręcznie. Można także dokonać typ klasy które są podklasą innych typów klas. Deklaracja klas z Num jest nieco długa ale tu jest pierwsza część class ( Eq a) => Num a where Jak już wcześniej wspomniano istnieje wiele miejsc w których możemy doczepić w konstruktorze klasy. Więc to jest jak pisanie class Num a where. Możemy w zasadzie powiedzieć że musimy dokonać typu instancji Eq, zanim będziemy mogli zrobić instancje z Num. Zanim jakiś typ może być uważany za numer, to ma sens gdyż możemy określić czy wartość tego typu można porównać czy nie. To wszystko to jest podklasa, to jedynie ograniczona klasa w klasie deklaracji. Kiedy określamy ciało funkcji w deklaracji klasy lub kiedy definiujemy je w deklaracji instancji możemy założyć że 'a' jest częścią Eq a więc możemy użyć == na wartościach tego typu.

59 class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) Z deklaracji typu możemy zauważyć że 'a' jest użyte jako konkretny typ ponieważ wszystkie typy funkcji muszą być konkretne. Dlatego nie możemy zrobić czegoś takiego: instance Eq Maybe where Ponieważ jak widzieliśmy 'a' jest konkretnego typu lecz Maybe nie jest konkretnego typu. Ten typ konstruktora może mieć jeden parametr i tworzy konkretny typ. Byłoby to także żmudne pisząc instance Eq (Maybe Int) where, instance Eq (Maybe Char) where, itp. dla każdego typu.

60 instance Eq ( Maybe m) where Just x == Just y = x == y Nothing == Nothing = True _ == _ = False To tak jakby powiedzieć że chcemy zrobić wszystkie typy z Maybe something instancji Eq. aktułalnie nie możemy napisać (Maybe something) ale zwykle decydujemy sie na pojedyńcze litery by były prawdziwe w stylu Haskella. (Maybe m) pełni tu rolę a gdzie class Eq a where. Kiedy maybe nie jest typu konkretnego maybe m jest. Okreslajac typ parametru ( m, jest małymi literami) powiedzieliśmy ze chcemy wszystkie typy które są w postaci Maybe m gdzie m jest dowolnego typu.

61 W JavaScript i innych typach języków, można umieścić niemal wszystko wewnątrz wyrażenia. Na przykład, można zrobić wszystko z następującymi czynnościami: if (0) alert("yeah!") else alert("no!"), if ("") alert ("YEAH!") else alert("no!"), if (false) alert("yeah") else alert("no!), itp., a wszystkie z nich będą wrzucać alert NO!. Jeśli to zrobisz, ( WHAT ), alert ( YEAH! ) else alert ( NO ), będzie alert( YEAH ), KLASY TYPU YES-NO

62 class YesNo a where yesno :: a -> Bool Całkiem proste. YesNo jest typem klasy określającej jedną funkcję. Ta funkcja przyjmuje jedną wartość typu, który może być uznane za wartość true-false, i mówi nam dla pewności czy to prawda czy nie. Zauważ, że gdy użyjemy a w funkcji, a staje się konkretnym typem. Następnie w kolejce zdefiniujemy kilka instancji. Dla liczb, będziemy zakładać (podobnie jak w JavaScript) każdy numer który nie jest 0 to true, a 0 jest false.

63 Dla liczb, będziemy zakładać (podobnie jak w JavaScript) każdy numer który nie jest 0 to true, a 0 jest false. instance YesNo Int where yesno 0 = False yesno _ = True Puste listy (przez rozszerzenie stringów są watości no, a niepuste listy są wartości yes. instance YesNo [a] where yesno [] = False yesno _ = True zauważ, jak po prostu umieściliśmy rodzaj parametru a w tym, aby lista była konkretnego typu, chociaż nie dokonywaliśmy żadnych założeń co do rodzaju który jest zawarty w wykazie. Wiemy również że Bool sam posiada również true i false, i jest to dość oczywiste, co jest czym.

64 instance YesNo Bool where yesno = id Id jest to po prostu zwykła funkcja biblioteki, która przyjmuje parametr i zwraca to samo, co ogólnie napiszemy. Zróbmy Maybe a w instancji: instance YesNo ( Maybe a) where yesno ( Just _) = True yesno Nothing = False Nie potrzebujemy klasy ograniczenia bo nie robimy założeń o treści Maybe. Po prostu powiedzieliśmy, że true jest to wartość Just i false jest Nothing. Sygnalizacja świetlna może być lub nie wartością. Pewnie. Jeśli jest czerwone musisz się zatrzymać, jeśli jest zielone to jedziesz. instance YesNo TrafficLight where yesno Red = False yesno _ = True

65 Przetestujmy: ghci > yesno $ length [] False ghci > yesno " haha " True ghci > yesno "" False ghci > yesno $ Just 0 True ghci > yesno True True ghci > yesno [] False ghci > yesno [0,0,0] True ghci > :t yesno yesno :: ( YesNo a) => a -> Bool Funkcja, naśladująca konstrukcje warunkową, ale działa z wartością YesNo yesnoif :: ( YesNo y) => y -> a -> a -> a yesnoif yesnoval yesresult noresult = if yesno yesnoval then yesresult else noresult Całkiem proste. Przyjmuje wartość yes-no i dwóch rzeczy. Jeśli wartość yes-no jest raczej tak, że zwraca pierwsze z dwóch rzeczy, w przeciwnym razie zwraca drugi z nich ghci > yesnoif [] " YEAH!" "NO!" "NO!" ghci > yesnoif [2,3,4] " YEAH!" "NO!" " YEAH!" ghci > yesnoif True " YEAH!" "NO!" " YEAH!" ghci > yesnoif ( Just 500) " YEAH!" "NO!" " YEAH!" ghci > yesnoif Nothing " YEAH!" "NO!" "NO!"

66 Funkcja, naśladująca konstrukcje warunkową, ale działa z wartością YesNo yesnoif :: ( YesNo y) => y -> a -> a -> a yesnoif yesnoval yesresult noresult = if yesno yesnoval then yesresult else noresult Całkiem proste. Przyjmuje wartość yes-no i dwóch rzeczy. Jeśli wartość yes-no jest True, to zwraca pierwszą z dwóch rzeczy, w przeciwnym razie zwraca drugą z nich ghci > yesnoif [] " YEAH!" "NO!" "NO!" ghci > yesnoif [2,3,4] " YEAH!" "NO!" " YEAH!" ghci > yesnoif True " YEAH!" "NO!" " YEAH!" ghci > yesnoif ( Just 500) " YEAH!" "NO!" " YEAH!" ghci > yesnoif Nothing " YEAH!" "NO!" "NO!"

67 Teraz mamy zamiar spojrzeć na klasę typu span class= label class Functor /span. Która jest w zasadzie odwzorowaniem. Typ listy jest częścią klasy typu Functor. class Functor f where fmap :: ( a -> b) -> f a -> f b Widzimy że definiuje jedną funkcję, fmap i nie ustawia żadnych domyślnych implementacji dla niego. W definicjach z klas typów typ zmiennej odgrywa rolę konkretnej klasy typu jak a w (==) :: (Eq a) =>a -> a -> Bool. Zamienia funkcję z jednego typu na inny oraz listę jednego typu i zwraca listę innego typu moi przyjaciele myślę ze mamy sam funktor. W rzeczywistości map jest fmap i działa tylko na listach. Tu jest jak lista jest instancją typu klasy Funktor instance Functor [] where fmap = map KLASA TYPU FUNKTOR

68 To jest to zauważ jak nie napisać instance funktor [a] where, bo z fmap :: (a -> b) -> f a -> f b widzimy że f może być konstruktorem jednego typu. [a] jest juz konkretnego typu, kiedy [] jest konstruktorem typu które wykonuje jeden typ i produkuje typy podobne do [Int], [String] lub nawet [[String]] Ponieważ na listach fmap to map możemy uzyskać takie same wyniki przy użyciu ich na listach map :: (a -> b ) -> [ a] -> [ b] ghci > fmap (*2) [1..3] [2,4,6] ghci > map (*2) [1..3] [2,4,6]

69 Typami które mogą działać jako pudełko ( box) mogą być funktory. Można myśleć o liście jako box które zawiera nieskończoną ilość małych przedziałów a wszystkie one mogą być puste.jeden może być pełny a pozostałe puste lub ich liczba może być pełna. Inną rzeczą która może być odwzorowana i wykonana w instancji functor jest typ tree.może ona być traktowana jako box ( pudełko) w sposób (posiada kilka lub nie ma wartości) i konstruktor tree trzyma dokładnie jeden typ parametru. Jeśli spojrzeć na fmap tak jak była wykonana tylko dla funkcji drzewa jej sygnatura będzie wyglądać (a -> b) -> Tree a -> Tree b zamierzamy użyć rekursji. Mapowanie na pustym drzewie będzie produkować puste drzewa, mapowanie na nie pustym drzewie będzie drzewo składające sie z naszej funkcji stosowane do korzenia i jego wartości lewego i prawego poddrzewa, tylko nasza funkcja będzie odwzorowana na nich. instance Functor Tree where fmap f EmptyTree = EmptyTree fmap f ( Node x leftsub rightsub ) = Node (f x) ( fmap f leftsub ) ( fmap f rightsub ) ghci > fmap (*2) EmptyTree EmptyTree ghci > fmap (*4) ( foldr treeinsert EmptyTree [5,7,3,2,1,7]) Node 28 ( Node 4 EmptyTree ( Node 8 EmptyTree ( Node 12 EmptyTree ( Node 20 EmptyTree EmptyTree )))) EmptyTree

70 RODZAJE I PEWNE TYPY FOO Typy konstruktorów mogą przyjmować różne parametry, ewentualnie produkować konkretne typy. Zalety rodzaji: ghci > :k Int Int :: * "*" oznacza że jest to konkretny typ, który nie przyjmuje żadnych parametrów wartości.

71 ghci > :k Maybe Int Maybe Int :: * Zastosowano typ parametru Maybe i otrzymaliśmy konkretny typ ( to co *->* oznacza równoległe lecz nie równoważne, typy i rodzaje są dwoma różnymi rzeczami :k używamy na typach aby uzyskać ich rodzaj. Tak samo możemy użyć :t na wartości aby uzyskać jego typ. Typy etykiet wartości i rodzaje etykiet typów są podobne do siebie.

72 Sposób działania Maybe ghci > :k Maybe Maybe :: * -> * Typ konstruktora Maybe bierze jeden rodzaj konretnego typu (jak int) następnie zwraca Maybe Int. Tak jak Int -> Int znaczy to że funkcja pobiera int i zwraca int, * -> * oznacza to że typ konstruktora bierze jeden konkretny typ i go zwraca.

73 ghci > :k Either Either :: * -> * -> * Either bierze dwa konkretne typy jako typy parametrów od produkcji konkretnego typu. Wygląda to tak że typy deklaracji funkcji pobierają dwie wartości które coś zwracają. Typy konstruktorów tak jak i funkcje możemy zastosować częściowo. ghci > :k Either String Either String :: * -> * ghci > :k Either String Int Either String Int :: * Kiedy chcemy zrobić Eitheri częścią Functor typu klas. Musimy częściowo zastosować je ponieważ Functor wymaga typów pobierających jeden parametr kiedy Either pobiera dwa. Innymi słowy Factor chce typy rodzaju *->*. Aby uzyskać typ rodzaju *->* zamiast orginalnego rodzaju *->*->*

74 Jeżeli patrzymy na definicje Functor ponownie class Functor f where fmap :: ( a -> b) -> f a -> f b To typ zmiennej f jest używana jako typ pobierający do produkcji konkretnego typ. Wiemy że ma stworzyć konkretny typ gdyż jest używany jako typ o wartości funkcji, i od tego możemy wnioskować że typy zaprzyjaźnione z Functor muszą być rodzaju *->*.

75 Definicja typu foo: class Tofu t where tofu :: j a -> t a j Ponieważ j a jest użyty jako typ wartości funkcji Tofu biorący jako parametr j a musi mieć rodzaj *. Zakładając * dla a możemy wnioskować że j może mieć rodzaj *->*. Widzimy że t produkuje konkretną wartość i przyjmuje ono dwa typy. I wiedząc że a ma rodzaj * i j ma rodzaj *->* możemy wnioskować że t musi mieć rodzaj *->(*->*)->* więc to ma konkretny typ 'a', typ konstruktora pobiera jeden konkretny typ (j) i tworzy konkretny typ Stwórzmy typ rodzaju *->(*->*)->* data Frank a b = Frank { frankfield :: b a} deriving ( Show ) Załóżmy * dla a co oznacza że b przyjmuje jeden typ parametru rodzaju*->*. Teraz znamy rodzaj a i b, a ponieważ są parametrami dla Franka widzimy że Frank ma rodzaj *->(*->*)->*. Pierwsza * reprezentuje a i (*->*) to b.

76 ghci > :t Frank { frankfield = Just " HAHA " } Frank { frankfield = Just " HAHA "} :: Frank [ Char ] Maybe ghci > :t Frank { frankfield = Node 'a ' EmptyTree EmptyTree } Frank { frankfield = Node 'a ' EmptyTree EmptyTree } :: Frank Char Tree ghci > :t Frank { frankfield = " YES "} Frank { frankfield = " YES "} :: Frank Char [] Ponieważ FrankField ma typ postaci a b, jego wartości muszą mieć podobnej postaci rodzaj. Więc może to być Just hahaha który ma typ Maybe [Char] lub może mieć wartość ['Y', 'e', 's'] który ma typ [Char]. Widzimy że typ wartości Frank odpowiada jego rodzajowi. [Char] ma rodzaj * i Maybe ma rodzaj *->* ponieważ w celu uzyskania wartości musi być konkretnego typu zatem musi być w pełni zastosowane. Każda wartość Frank blah blaah ma rodzaj *.

77 data Barry t k p = Barry { yabba :: p, dabba :: t k } Functor chce typ rodzaju *->* ale Barry go nie posiada. Więc widzimy pobieranie 3 typów parametrów: something -> something -> something -> *. p jest konkretnego typu a więc ma rodzaj *. Dla k zakładamy gwiazdkę więc tym samym t jest rodzaju *->*. Teraz zamieniamy te rodzaje z czymś co jest używane jako zmienne i widzimy że ma rodzaj: (* -> *) -> * -> * -> *. ghci > :k Barry Barry :: (* -> *) -> * -> * -> *

78 Teraz aby ten typ był częścią Fuktor musimy częściowo zastosować dwa pierwsze typy parametrów więc jesteśmy z lewej *->*. Oznacza to że początek zgłoszenia instancji będzie wynosić instance Functor (Barry a b) where. Jeśli spojrzymy na fmap jak by był wykonany dla Barry miałby rodzaj fmap :: (a -> b) -> Barry c d a -> Barry c d b ponieważ chcemy zamienić Functor's f z Barry c d. Trzecim typem parametru z Barry musimy zamienić i widzimy że jest wygodne dla własnego pola. instance Functor ( Barry a b ) where fmap f ( Barry { yabba = x, dabba = y }) = Barry { yabba = f x, dabba = y} Właśnie zmapowaliśmy f w pierwszym polu.

TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4

TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4 TWORZENIE SWOICH TYPÓW I TYPÓW KLAS HASKELL (RODZIAŁ 8) ZAJĘCIA 4 Wprowadzenie do typów algebraicznych WPROWADZENIE DO TYPÓW ALGEBRAICZNYCH Słowo data oznacza zdefiniowanie nowego typu danych Typ Bool

Bardziej szczegółowo

- nawiasy kwadratowe oznaczają, że to lista

- nawiasy kwadratowe oznaczają, że to lista Haskell jest statycznym typem języka: - wszystkie typy i wyrażenia są znane w czasie kompilacji ( zwiększa to bezpieczeństwo kodu). Podawanie typów zmiennych i argumentów funkcji jest zbędne, gdyż Haskel

Bardziej szczegółowo

Typy, klasy typów, składnie w funkcji

Typy, klasy typów, składnie w funkcji Typy, klasy typów, składnie w funkcji Typy w Haskell Każde wyrażenie w Haskell posiada zdefiniowany typ. Dzięki temu już na etapie kompilacji kodu następuje sprawdzenie poprawności kodu i zabezpiecza nas

Bardziej szczegółowo

Haskell Moduły Ładowanie

Haskell Moduły Ładowanie Haskell Moduły Moduł zestaw powiązanych funkcji, typów, typeclass. Program w Haskellu często jest modułem, który ładuje inne moduły a następnie wykorzystuje zdefiniowane w nich funkcje w celu realizacji

Bardziej szczegółowo

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Część XXII C++ w Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Ćwiczenie 1 1. Utwórz nowy projekt w Dev C++ i zapisz go na

Bardziej szczegółowo

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost; Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów Operatory są elementami języka C++. Istnieje zasada, że z elementami języka, takimi jak np. słowa kluczowe, nie można dokonywać żadnych zmian, przeciążeń, itp. PRZECIĄŻANIE OPERATORÓW Ale dla operatorów

Bardziej szczegółowo

Podstawy programowania skrót z wykładów:

Podstawy programowania skrót z wykładów: Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace

Bardziej szczegółowo

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec PROE wykład 2 operacje na wskaźnikach dr inż. Jacek Naruniec Zmienne automatyczne i dynamiczne Zmienne automatyczne: dotyczą kontekstu, po jego opuszczeniu są usuwane, łatwiejsze w zarządzaniu od zmiennych

Bardziej szczegółowo

TEMAT : KLASY DZIEDZICZENIE

TEMAT : KLASY DZIEDZICZENIE TEMAT : KLASY DZIEDZICZENIE Wprowadzenie do dziedziczenia w języku C++ Język C++ możliwa tworzenie nowej klasy (nazywanej klasą pochodną) w oparciu o pewną wcześniej zdefiniowaną klasę (nazywaną klasą

Bardziej szczegółowo

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main. Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo

Bardziej szczegółowo

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec PROE wykład 3 klasa string, przeciążanie funkcji, operatory dr inż. Jacek Naruniec Przypomnienie z ostatnich wykładów Konstruktory/destruktory i kolejność ich wywołania w złożonej klasie. Referencja Obiekty

Bardziej szczegółowo

Systemy operacyjne. Laboratorium 9. Perl wyrażenia regularne. Jarosław Rudy Politechnika Wrocławska 28 lutego 2017

Systemy operacyjne. Laboratorium 9. Perl wyrażenia regularne. Jarosław Rudy Politechnika Wrocławska 28 lutego 2017 Systemy operacyjne Laboratorium 9 Perl wyrażenia regularne Jarosław Rudy Politechnika Wrocławska 28 lutego 2017 Temat obejmuje wykorzystanie wyrażeń regularnych w perlu. Wyrażenia same w sobie są w zasadzie

Bardziej szczegółowo

Informatyka II. Laboratorium Aplikacja okienkowa

Informatyka II. Laboratorium Aplikacja okienkowa Informatyka II Laboratorium Aplikacja okienkowa Założenia Program będzie obliczał obwód oraz pole trójkąta na podstawie podanych zmiennych. Użytkownik będzie poproszony o podanie długości boków trójkąta.

Bardziej szczegółowo

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Jak napisać program obliczający pola powierzchni różnych figur płaskich? Część IX C++ Jak napisać program obliczający pola powierzchni różnych figur płaskich? Na początku, przed stworzeniem właściwego kodu programu zaprojektujemy naszą aplikację i stworzymy schemat blokowy

Bardziej szczegółowo

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany KLASA UCZEN Napisz deklarację klasy Uczen, w której przechowujemy następujące informacje o uczniu: imię, nazwisko, średnia (pola prywatne), poza tym klasa zawiera metody: konstruktor bezparametrowy (nie

Bardziej szczegółowo

Tworzenie własnych typów. danych oraz klas typów

Tworzenie własnych typów. danych oraz klas typów Justyna Łowicka Tworzenie własnych typów danych oraz klas typów Algebraiczne typy danych konstruktorów umieszczonych w deklaracji data. Zobaczmy, jak typ Bool jest zdefiniowany w bibliotece standardowej.

Bardziej szczegółowo

W powyższym kodzie utworzono wyliczenie dni tygodnia.

W powyższym kodzie utworzono wyliczenie dni tygodnia. Typ wyliczeniowy (zwane również enumeration lub enum) jest to typ danych składający się z zestawu nazwanych wartości. Do zmiennej, która została zadeklarowana jako typ wyliczeniowy może być przypisane

Bardziej szczegółowo

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy WSKAŹNIKI KLASOWE WSKAŹNIKI KLASOWE Wskaźniki klasowe Każdy obiekt zajmuje fragment pamięci i wszystkie obiekty tego samego typu zajmują fragmenty pamięci tej samej długości początek miejsca w pamięci zajmowanego przez

Bardziej szczegółowo

Elementy języka Haskell

Elementy języka Haskell Elementy języka Haskell Cechy języka Historia języka Proste przykłady Środowisko interakcyjne Typy i klasy Definiowanie funkcji Wyrażenia listowe Deklarowanie typów, danych i klas Monady Cechy języka zwięzłe

Bardziej szczegółowo

Warunek wielokrotnego wyboru switch... case

Warunek wielokrotnego wyboru switch... case Warunek wielokrotnego wyboru switch... case Działanie instrukcji switch jest zupełnie inne niż w przypadku instrukcji if o czym będziesz mógł się przekonać w niniejszym rozdziale. Różnice pomiędzy instrukcjami

Bardziej szczegółowo

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany KLASA UCZEN Napisz deklarację klasy Uczen, w której przechowujemy następujące informacje o uczniu: imię, nazwisko, średnia (pola prywatne), poza tym klasa zawiera metody: konstruktor bezparametrowy (nie

Bardziej szczegółowo

W dowolnym momencie można zmienić typ wskaźnika.

W dowolnym momencie można zmienić typ wskaźnika. c++ Wskaźniki mają jeszcze jedną przydatną cechę. W dowolnym momencie można zmienić typ wskaźnika. Robi się to za pomocą operatora rzutowania. Najpierw zdefiniujemy sobie wsk_uniwersalny mogący pokazywać

Bardziej szczegółowo

Definicje wyższego poziomu

Definicje wyższego poziomu Definicje wyższego poziomu Interpreter Scheme-a nie będzie narzekad w przypadku wystąpienia niezdefionowanej zmiennej w ciele wyrażenia lambda dopóki nie będzie zastosowana Przykład braku informacji o

Bardziej szczegółowo

Podstawy programowania w C++

Podstawy programowania w C++ Podstawy programowania w C++ Liczby w jaki sposób komputery je widzą? Opracował: Andrzej Nowak Bibliografia: CPA: PROGRAMMING ESSENTIALS IN C++ https://www.netacad.com Czy wiesz, jak komputery wykonują

Bardziej szczegółowo

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel Wstęp do programowania Drzewa podstawowe techniki Piotr Chrząstowski-Wachtel Drzewa wyszukiwań Drzewa często służą do przechowywania informacji. Jeśli uda sie nam stworzyć drzewo o niewielkiej wysokości

Bardziej szczegółowo

SQL - Structured Query Language -strukturalny język zapytań SQL SQL SQL SQL

SQL - Structured Query Language -strukturalny język zapytań SQL SQL SQL SQL Wprowadzenie do SQL SQL - Structured Query Language -strukturalny język zapytań Światowy standard przeznaczony do definiowania, operowania i sterowania danymi w relacyjnych bazach danych Powstał w firmie

Bardziej szczegółowo

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else.

Nazwa implementacji: Nauka języka Python wyrażenia warunkowe. Autor: Piotr Fiorek. Opis implementacji: Poznanie wyrażeń warunkowych if elif - else. Nazwa implementacji: Nauka języka Python wyrażenia warunkowe Autor: Piotr Fiorek Opis implementacji: Poznanie wyrażeń warunkowych if elif - else. Nasz kalkulator umie już liczyć, ale potrafi przeprowadzać

Bardziej szczegółowo

Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki Konwersje napis liczba Struktury, unie Scanf / printf Wskaźniki Konwersje liczba napis Ćwiczenia 1. Napisz aplikację, która na wejściu dostaje napis postaci W Roku Pańskim 1345, władca Henryk 12,

Bardziej szczegółowo

Programowanie strukturalne i obiektowe. Funkcje

Programowanie strukturalne i obiektowe. Funkcje Funkcje Często w programach spotykamy się z sytuacją, kiedy chcemy wykonać określoną czynność kilka razy np. dodać dwie liczby w trzech miejscach w programie. Oczywiście moglibyśmy to zrobić pisząc trzy

Bardziej szczegółowo

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek].

Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek]. ABAP/4 Instrukcja IF Opis: Instrukcja warunkowa Składnia: IF [NOT] warunek [AND [NOT] warunek] [OR [NOT] warunek]. [ELSEIF warunek. ] [ELSE. ] ENDIF. gdzie: warunek dowolne wyrażenie logiczne o wartości

Bardziej szczegółowo

Programowanie. Lista zadań nr 15. Na ćwiczenia 11, 19 i 23 czerwca 2008

Programowanie. Lista zadań nr 15. Na ćwiczenia 11, 19 i 23 czerwca 2008 Programowanie Lista zadań nr 15 Na ćwiczenia 11, 19 i 23 czerwca 2008 Zadanie 1. Pokaż, że w systemie z polimorfizmem parametrycznym można napisać program P n rozmiaru O(n), którego typ ma rozmiar 2 2Ω(n).

Bardziej szczegółowo

Szablony klas, zastosowanie szablonów w programach

Szablony klas, zastosowanie szablonów w programach Szablony klas, zastosowanie szablonów w programach 1. Szablony klas i funkcji 2. Szablon klasy obsługującej uniwersalną tablicę wskaźników 3. Zastosowanie metody zwracającej przez return referencję do

Bardziej szczegółowo

Języki i Paradygmaty Programowania

Języki i Paradygmaty Programowania Języki i Paradygmaty Programowania Odkrywamy Haskell Marcin Benke 24 lutego 2014 Odkrywamy Haskell Haskell zasadniczo kompilowany, ale też interpreter: ghci $ ghci GHCi, version 7.6.2: http://www.haskell.org/ghc/

Bardziej szczegółowo

4. Funkcje. Przykłady

4. Funkcje. Przykłady 4. Funkcje Przykłady 4.1. Napisz funkcję kwadrat, która przyjmuje jeden argument: długość boku kwadratu i zwraca pole jego powierzchni. Używając tej funkcji napisz program, który obliczy pole powierzchni

Bardziej szczegółowo

Rozdział 4 KLASY, OBIEKTY, METODY

Rozdział 4 KLASY, OBIEKTY, METODY Rozdział 4 KLASY, OBIEKTY, METODY Java jest językiem w pełni zorientowanym obiektowo. Wszystkie elementy opisujące dane, za wyjątkiem zmiennych prostych są obiektami. Sam program też jest obiektem pewnej

Bardziej szczegółowo

Typy wyliczeniowe Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Typy wyliczeniowe Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki Typy wyliczeniowe Konwersje napis liczba Struktury, unie Scanf / printf Wskaźniki Typy wyliczeniowe Służą do łatwiejszej kontroli nad stałymi Ustawianie parametrów o ściśle określonym zbiorze wartości

Bardziej szczegółowo

WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK

WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK WEJŚCIE/WYJŚCIE HASKELL ŁUKASZ PAWLAK DARIUSZ KRYSIAK W Haskellu funkcje nie mogą zmieniać stanów (w tym np. zmieniać wartości zmiennej). Funkcja wywołana z pewnymi ustalonymi argumentami musi zwracać

Bardziej szczegółowo

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład. Część XVII C++ Funkcje Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład. 2 3 Tworzymy deklarację i definicję funkcji o nazwie pobierzln() Funkcja

Bardziej szczegółowo

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np Klasy Klasa jest nowym typem danych zdefiniowanym przez użytkownika Wartości takiego typu nazywamy obiektami Najprostsza klasa jest po prostu strukturą, np struct Zespolona { Klasy jako struktury z operacjami

Bardziej szczegółowo

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Programowanie obiektowe i C++ dla matematyków

Programowanie obiektowe i C++ dla matematyków Programowanie obiektowe i C++ dla matematyków Bartosz Szreder szreder (at) mimuw... 22 XI 2011 Uwaga! Ponieważ już sobie powiedzieliśmy np. o wskaźnikach i referencjach, przez które nie chcemy przegrzebywać

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

PHP 5 język obiektowy

PHP 5 język obiektowy PHP 5 język obiektowy Wprowadzenie Klasa w PHP jest traktowana jak zbiór, rodzaj różnych typów danych. Stanowi przepis jak stworzyć konkretne obiekty (instancje klasy), jest definicją obiektów. Klasa reprezentuje

Bardziej szczegółowo

Składnia funkcji i Rekurencja w języku Haskell

Składnia funkcji i Rekurencja w języku Haskell Składnia funkcji i w języku Haskell Tomasz Ostrowski, Adrian Niechciał, Michał Workiewicz, Marcin Wilk 26 marca 2015 Składnia funkcji i w języku Haskell Spis treści Składnia funkcji Tomasz Ostrowski Adrian

Bardziej szczegółowo

C++ Przeładowanie operatorów i wzorce w klasach

C++ Przeładowanie operatorów i wzorce w klasach C++ i wzorce w klasach Andrzej Przybyszewski numer albumu: 89810 14 listopada 2009 Ogólnie Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje

Bardziej szczegółowo

Wstęp do programowania obiektowego, wykład 7

Wstęp do programowania obiektowego, wykład 7 Wstęp do programowania obiektowego, wykład 7 Klasy i funkcje abstrakcyjne Przeciążanie funkcji Definiowanie i interpretacja złożonych typów danych w C++ Wskaźniki do funkcji 1 KLASA ABSTRAKCYJNA 2 Klasa

Bardziej szczegółowo

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny Wstęp do Programowania potok funkcyjny Marcin Kubica 2016/2017 Outline Moduły i bariery abstrakcji 1 Moduły i bariery abstrakcji Moduły co to jest i po co to jest? Duży system dzielimy na mniejsze, łatwiejsze

Bardziej szczegółowo

Podstawy algorytmiki i programowania - wykład 4 C-struktury

Podstawy algorytmiki i programowania - wykład 4 C-struktury 1 Podstawy algorytmiki i programowania - wykład 4 C-struktury Treści prezentowane w wykładzie zostały oparte o: S. Prata, Język C++. Szkoła programowania. Wydanie VI, Helion, 2012 www.cplusplus.com Jerzy

Bardziej szczegółowo

Zasady programowania Dokumentacja

Zasady programowania Dokumentacja Marcin Kędzierski gr. 14 Zasady programowania Dokumentacja Wstęp 1) Temat: Przeszukiwanie pliku za pomocą drzewa. 2) Założenia projektu: a) Program ma pobierać dane z pliku wskazanego przez użytkownika

Bardziej szczegółowo

Aplikacje w środowisku Java

Aplikacje w środowisku Java Aplikacje w środowisku Java Materiały do zajęć laboratoryjnych Klasy i obiekty - dziedziczenie mgr inż. Kamil Zieliński Katolicki Uniwersytet Lubelski Jana Pawła II 2018/2019 W ramach poprzedniego laboratorium

Bardziej szczegółowo

Podstawy JavaScript ćwiczenia

Podstawy JavaScript ćwiczenia Podstawy JavaScript ćwiczenia Kontekst:

Bardziej szczegółowo

Programowanie Komputerów

Programowanie Komputerów Programowanie Komputerów Łukasz Kuszner pokój 209, WETI http://www.kaims.pl/ kuszner/ kuszner@eti.pg.gda.pl Wykład 30 godzin, Laboratoria 30 godzin 2012/ Strona 1 z 17 1. Typy i zmienne Jak wiemy, komputer

Bardziej szczegółowo

Szablony funkcji i szablony klas

Szablony funkcji i szablony klas Bogdan Kreczmer bogdan.kreczmer@pwr.wroc.pl Zakład Podstaw Cybernetyki i Robotyki Instytut Informatyki, Automatyki i Robotyki Politechnika Wrocławska Kurs: Copyright c 2011 Bogdan Kreczmer Niniejszy dokument

Bardziej szczegółowo

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p. Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni Wykład 3 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Abstrakcja funkcyjna Struktury Klasy hermetyzacja

Bardziej szczegółowo

Operatory AND, OR, NOT, XOR Opracował: Andrzej Nowak Bibliografia:

Operatory AND, OR, NOT, XOR Opracował: Andrzej Nowak Bibliografia: Operatory logiczne Komputery i ich logika AND - && Podstawy programowania w C++ Operatory AND, OR, NOT, XOR Opracował: Andrzej Nowak Bibliografia: CPA: PROGRAMMING ESSENTIALS IN C++ https://www.netacad.com

Bardziej szczegółowo

Drzewo binarne BST. LABORKA Piotr Ciskowski

Drzewo binarne BST. LABORKA Piotr Ciskowski Drzewo binarne BST LABORKA Piotr Ciskowski zadanie 1. drzewo binarne - 1 Zaimplementuj drzewo binarne w postaci: klasy Osoba przechowującej prywatne zmienne: liczbę całkowitą to będzie klucz, wg którego

Bardziej szczegółowo

Programowanie 3 - Funkcje, pliki i klasy

Programowanie 3 - Funkcje, pliki i klasy Instytut Informatyki Uniwersytetu Śląskiego Laborki funkcja; parametry funkcji; typ zwracany; typ void; funkcje bez parametrów; napis.length() - jako przykład funkcji. Zadania funkcja dodająca dwie liczby;

Bardziej szczegółowo

Języki i techniki programowania Ćwiczenia 2

Języki i techniki programowania Ćwiczenia 2 Języki i techniki programowania Ćwiczenia 2 Autor: Marcin Orchel Spis treści: Język C++... 5 Przekazywanie parametrów do funkcji... 5 Przekazywanie parametrów w Javie.... 5 Przekazywanie parametrów w c++...

Bardziej szczegółowo

Wykład 8: klasy cz. 4

Wykład 8: klasy cz. 4 Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD

Bardziej szczegółowo

Moduły. Źródło: a) Wczytywanie modułów. interparse rozdziela każdy element listy wcześniej podanym znakiem

Moduły. Źródło:  a) Wczytywanie modułów. interparse rozdziela każdy element listy wcześniej podanym znakiem Autor: Roman Gęsiarz Moduły Źródło: http://learnyouahaskell.com/modules a) Wczytywanie modułów b) Data.List c) Data.Char d) Data.Map e) Data.Set f) Tworzenie własnych modułów Łódź, dnia 25.03.2017 r. Ad.

Bardziej szczegółowo

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.)

Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.) Swift (pol. jerzyk) nowy język programowania zaprezentowany latem 2014 r. (prace od 2010 r.) przeznaczony do programowania zarówno pod ios jak i Mac OS X bazuje na logice Objective-C bez kompatybilności

Bardziej szczegółowo

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne

Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne Funkcje przeciążone, konstruktory kopiujące, argumenty domyślne Przeciążenie funkcji polega na użyciu funkcji z tą samą nazwą, które mają różne listy argumentów(różne typy, różna ilość lub to i inne).

Bardziej szczegółowo

Klasy abstrakcyjne i interfejsy

Klasy abstrakcyjne i interfejsy Klasy abstrakcyjne i interfejsy Streszczenie Celem wykładu jest omówienie klas abstrakcyjnych i interfejsów w Javie. Czas wykładu 45 minut. Rozwiązanie w miarę standardowego zadania matematycznego (i nie

Bardziej szczegółowo

Lekcja : Tablice + pętle

Lekcja : Tablice + pętle Lekcja : Tablice + pętle Wprowadzenie Oczywiście wiesz już jak dużo można osiągnąć za pomocą tablic oraz jak dużo można osiągnąć za pomocą pętli, jednak tak naprawdę prawdziwe możliwości daje połączenie

Bardziej szczegółowo

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h] 1. Typy. Java jest językiem programowania z silnym systemem kontroli typów. To oznacza, że każda zmienna, atrybut czy parametr ma zadeklarowany typ. Kompilator wylicza typy wszystkich wyrażeń w programie

Bardziej szczegółowo

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Dziedziczenie Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasy Student oraz Pracownik: class Student class Pracownik

Bardziej szczegółowo

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Załóżmy, że uprawiamy jogging i chcemy monitorować swoje postępy. W tym celu napiszemy program, który zlicza, ile czasu

Bardziej szczegółowo

Język programowania zbiór reguł określających, które ciągi symboli tworzą program komputerowy oraz jakie obliczenia opisuje ten program.

Język programowania zbiór reguł określających, które ciągi symboli tworzą program komputerowy oraz jakie obliczenia opisuje ten program. PYTHON Język programowania zbiór reguł określających, które ciągi symboli tworzą program komputerowy oraz jakie obliczenia opisuje ten program. Aby program napisany w danym języku mógł być wykonany, niezbędne

Bardziej szczegółowo

Struktura drzewa w MySQL. Michał Tyszczenko

Struktura drzewa w MySQL. Michał Tyszczenko Struktura drzewa w MySQL Michał Tyszczenko W informatyce drzewa są strukturami danych reprezentującymi drzewa matematyczne. W naturalny sposób reprezentują hierarchię danych toteż głównie do tego celu

Bardziej szczegółowo

Wysokość drzewa Głębokość węzła

Wysokość drzewa Głębokość węzła Drzewa Drzewa Drzewo (ang. tree) zbiór węzłów powiązanych wskaźnikami, spójny i bez cykli. Drzewo posiada wyróżniony węzeł początkowy nazywany korzeniem (ang. root). Drzewo ukorzenione jest strukturą hierarchiczną.

Bardziej szczegółowo

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny Wstęp do Programowania potok funkcyjny Marcin Kubica 2010/2011 Outline 1 Pojęcie typu Definition (Typ danych) Typ danych to zbiór wartości wraz z zestawem podstawowych operacji na tych wartościach. Typy

Bardziej szczegółowo

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno Instrukcja laboratoryjna 5 Podstawy programowania 2 Temat: Drzewa binarne Przygotował: mgr inż. Tomasz Michno 1 Wstęp teoretyczny Drzewa są jedną z częściej wykorzystywanych struktur danych. Reprezentują

Bardziej szczegółowo

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w

Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w Wyrażenie include(sciezka_do_pliku) pozwala na załadowanie (wnętrza) pliku do skryptu php. Plik ten może zawierać wszystko, co może się znaleźć w obrębie skryptu. Wyrażenia include() i require() są niemal

Bardziej szczegółowo

Paradygmaty programowania

Paradygmaty programowania Paradygmaty programowania Jacek Michałowski, Piotr Latanowicz 15 kwietnia 2014 Jacek Michałowski, Piotr Latanowicz () Paradygmaty programowania 15 kwietnia 2014 1 / 12 Zadanie 1 Zadanie 1 Rachunek predykatów

Bardziej szczegółowo

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał REKURENCJA W JĘZYKU HASKELL Autor: Walczak Michał CZYM JEST REKURENCJA? Rekurencja zwana rekursją, polega na wywołaniu przez funkcję samej siebie. Algorytmy rekurencyjne zastępują w pewnym sensie iteracje.

Bardziej szczegółowo

Czym są właściwości. Poprawne projektowanie klas

Czym są właściwości. Poprawne projektowanie klas Z akcesorów get i set korzysta każdy kto programuje w C#. Stanowią one duże udogodnienie w programowaniu obiektowym. Zapewniają wygodę, bezpieczeństwo i znacząco skracają kod. Akcesory są ściśle związane

Bardziej szczegółowo

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

dodatkowe operacje dla kopca binarnego: typu min oraz typu max: ASD - ćwiczenia IX Kopce binarne własność porządku kopca gdzie dla każdej trójki wierzchołków kopca (X, Y, Z) porządek etykiet elem jest następujący X.elem Y.elem oraz Z.elem Y.elem w przypadku kopca typu

Bardziej szczegółowo

Podstawy Programowania C++

Podstawy Programowania C++ Wykład 3 - podstawowe konstrukcje Instytut Automatyki i Robotyki Warszawa, 2014 Wstęp Plan wykładu Struktura programu, instrukcja przypisania, podstawowe typy danych, zapis i odczyt danych, wyrażenia:

Bardziej szczegółowo

Języki programowania Haskell

Języki programowania Haskell Języki programowania Haskell zadanie projektowe nr. 4 2014/15 K. Turowski, T. Goluch 1. Kompilacja, uruchamianie i Hello world Kompilacja i uruchamianie: ghc --make hello.hs./hello Interaktywny interpreter:

Bardziej szczegółowo

JAVA W SUPER EXPRESOWEJ PIGUŁCE

JAVA W SUPER EXPRESOWEJ PIGUŁCE JAVA W SUPER EXPRESOWEJ PIGUŁCE Obiekt Obiekty programowe to zbiór własności i zachowań (zmiennych i metod). Podobnie jak w świecie rzeczywistym obiekty posiadają swój stan i zachowanie. Komunikat Wszystkie

Bardziej szczegółowo

Aby przejść do edycji w tym module należy wybrać zakładkę "Dla Pracowników" -> "Sprawdziany".

Aby przejść do edycji w tym module należy wybrać zakładkę Dla Pracowników -> Sprawdziany. Sprawdziany Sprawdziany Moduł "Sprawdziany" oferuje osobom prowadzącym zajęcia wygodny sposób informowania studentów o wynikach/ocenach jakie uzyskali (np. z kartkówek, różnego rodzaju zadań, ogólne jakie

Bardziej szczegółowo

ZMIENNE. Podstawy PHP

ZMIENNE. Podstawy PHP ZMIENNE Podstawy PHP zmienna - to obiekt w programowaniu, który przechowuje różnego rodzaju dane niezbędne do działania programu. Zmienna podczas działania programu może zmieniad swoje wartości (jak wskazuje

Bardziej szczegółowo

Struktury, unie, formatowanie, wskaźniki

Struktury, unie, formatowanie, wskaźniki Struktury, unie, formatowanie, wskaźniki 1. Napisz aplikację, która na wejściu dostaje napis postaci W Roku Pańskim 1345, władca Henryk 12, na rzecz swoich 143209 poddanych uchwalił dekret o 20 procentowej

Bardziej szczegółowo

Język ludzki kod maszynowy

Język ludzki kod maszynowy Język ludzki kod maszynowy poziom wysoki Język ludzki (mowa) Język programowania wysokiego poziomu Jeśli liczba punktów jest większa niż 50, test zostaje zaliczony; w przeciwnym razie testu nie zalicza

Bardziej szczegółowo

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie Część X C++ Typ znakowy służy do reprezentacji pojedynczych znaków ASCII, czyli liter, cyfr, znaków przestankowych i innych specjalnych znaków widocznych na naszej klawiaturze (oraz wielu innych, których

Bardziej szczegółowo

PHP: bloki kodu, tablice, obiekty i formularze

PHP: bloki kodu, tablice, obiekty i formularze 1 PHP: bloki kodu, tablice, obiekty i formularze SYSTEMY SIECIOWE Michał Simiński 2 Bloki kodu Blok if-else Switch Pętle Funkcje Blok if-else 3 W PHP blok if i blok if-else wyglądają tak samo i funkcjonują

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

Część 4 życie programu

Część 4 życie programu 1. Struktura programu c++ Ogólna struktura programu w C++ składa się z kilku części: część 1 część 2 część 3 część 4 #include int main(int argc, char *argv[]) /* instrukcje funkcji main */ Część

Bardziej szczegółowo

Aplikacje w środowisku Java

Aplikacje w środowisku Java Aplikacje w środowisku Java Materiały do zajęć laboratoryjnych Klasy i obiekty - wprowadzenie mgr inż. Kamil Zieliński Katolicki Uniwersytet Lubelski Jana Pawła II 2018/2019 Klasa zbiór pól i metod Obiekt

Bardziej szczegółowo

Wykład 5: Klasy cz. 3

Wykład 5: Klasy cz. 3 Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu

Bardziej szczegółowo

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Temat 1: Podstawowe pojęcia: program, kompilacja, kod Temat 1: Podstawowe pojęcia: program, kompilacja, kod wynikowy. Przykłady najprostszych programów. Definiowanie zmiennych. Typy proste. Operatory: arytmetyczne, przypisania, inkrementacji, dekrementacji,

Bardziej szczegółowo

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest Pętle Pętla to pewien fragment kodu, który jest wykonywany wielokrotnie. Wyobraź sobie taką sytuację. Piszesz program do szyfrowania danych. Dane są szyfrowane kolejno bajt po bajcie. Załóżmy, że plik

Bardziej szczegółowo

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek Nazwa implementacji: Nauka języka Python pętla for Autor: Piotr Fiorek Opis implementacji: Poznanie innego rodzaju pętli, jaką jest pętla for w języku Python. Składnia pętli for jest następująca: for

Bardziej szczegółowo

Interfejsy i klasy wewnętrzne

Interfejsy i klasy wewnętrzne Interfejsy i klasy wewnętrzne mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Interfejs klasy sposób komunikacji z jej obiektami (zestaw składowych publicznych). Określa on zestaw

Bardziej szczegółowo

1 Podstawy c++ w pigułce.

1 Podstawy c++ w pigułce. 1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,

Bardziej szczegółowo

3. Instrukcje warunkowe

3. Instrukcje warunkowe . Instrukcje warunkowe Przykłady.1. Napisz program, który pobierze od użytkownika liczbę i wypisze na ekran słowo ujemna lub nieujemna, w zależności od tego czy dana liczba jest ujemna czy nie. 1 #include

Bardziej szczegółowo

Drzewa BST i AVL. Drzewa poszukiwań binarnych (BST)

Drzewa BST i AVL. Drzewa poszukiwań binarnych (BST) Drzewa ST i VL Drzewa poszukiwań binarnych (ST) Drzewo ST to dynamiczna struktura danych (w formie drzewa binarnego), która ma tą właściwość, że dla każdego elementu wszystkie elementy w jego prawym poddrzewie

Bardziej szczegółowo

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki Turbo Pascal jest językiem wysokiego poziomu, czyli nie jest rozumiany bezpośrednio dla komputera, ale jednocześnie jest wygodny dla programisty,

Bardziej szczegółowo