HASKELL. Higher order functions, Modules. Janusz Bugajny Piotr Rogulski Łukasz Antoszkiewicz

Podobne dokumenty
Haskell Moduły Ładowanie

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

Moduł to zbiór powiązanych ze sobą funkcji, typów i klas typu. Język Haskell stanowi zbiór modułów, gdzie moduł główny załącza pozostałe moduły w

1 Podstawy c++ w pigułce.

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Podstawy programowania. Podstawy C# Tablice

1 Podstawy c++ w pigułce.

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

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

Definicje wyższego poziomu

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

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

Podstawy Programowania Podstawowa składnia języka C++

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

Języki programowania Haskell

WYRAŻENIA ALGEBRAICZNE

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

Wstęp do Programowania potok funkcyjny

Programowanie i struktury danych

Definicje. Algorytm to:

Podstawy Programowania C++

Urządzenia Techniki. Klasa I TI. System dwójkowy (binarny) -> BIN. Przykład zamiany liczby dziesiętnej na binarną (DEC -> BIN):

Laboratorium Wstawianie skryptu na stroną: 2. Komentarze: 3. Deklaracja zmiennych

Wstęp do programowania

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

Wstęp do programowania

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

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

Pętla for. Matematyka dla ciekawych świata -19- Scilab. for i=1:10... end. for k=4:-1:1... end. k=3 k=4. k=1. k=2

4. Funkcje. Przykłady

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

PHP: bloki kodu, tablice, obiekty i formularze

Programowanie w VB Proste algorytmy sortowania

Paradygmaty programowania

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Python wprowadzenie. Warszawa, 24 marca PROGRAMOWANIE I SZKOLENIA

Dla człowieka naturalnym sposobem liczenia jest korzystanie z systemu dziesiętnego, dla komputera natomiast korzystanie z zapisu dwójkowego

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

Wykresy i interfejsy użytkownika

12. Wprowadzenie Sygnały techniki cyfrowej Systemy liczbowe. Matematyka: Elektronika:

Systemy GIS Tworzenie zapytań w bazach danych

SUM Edukacja Techniczno Informatyczna Języki i Systemy Programowania. Wykład 3. dr Artur Bartoszewski - WYKŁAD: Języki i Systemy Programowania,

Liczby losowe i pętla while w języku Python

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Java Podstawy. Michał Bereta

KOTLIN. Język programowania dla Androida

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

SQL (ang. Structured Query Language)

Programowanie w Baltie klasa VII

Wykład 3 Składnia języka C# (cz. 2)

Myśl w języku Python! : nauka programowania / Allen B. Downey. Gliwice, cop Spis treści

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Zadanie 1. Zmiana systemów. Zadanie 2. Szyfr Cezara. Zadanie 3. Czy liczba jest doskonała. Zadanie 4. Rozkład liczby na czynniki pierwsze Zadanie 5.

Część 4 życie programu

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

I. Podstawy języka C powtórka

Systemy liczbowe używane w technice komputerowej

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

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

Języki i Paradygmaty Programowania

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Zadanie 2: Arytmetyka symboli

Języki i techniki programowania Ćwiczenia 4 Wzorce

Tablice. Jones Stygar na tropie zmiennych

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

Funkcje są prawdopodobnie najważniejszą częścią każdego poważnego programu (w każdym języku programowania).

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk

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.

Znaki w tym systemie odpowiadają następującym liczbom: I=1, V=5, X=10, L=50, C=100, D=500, M=1000

1. Wprowadzenie do języka PHP

UNIWERSYTET RZESZOWSKI KATEDRA INFORMATYKI

1259 (10) = 1 * * * * 100 = 1 * * * *1

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

Programowanie w języku Python. Grażyna Koba

Tabela wewnętrzna - definicja

ZASADY PROGRAMOWANIA KOMPUTERÓW

Programowanie strukturalne i obiektowe. Funkcje

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

- nawiasy kwadratowe oznaczają, że to lista

Składnia funkcji i Rekurencja w języku Haskell

Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego

1. Informatyka - dyscyplina naukowa i techniczna zajmująca się przetwarzaniem informacji.

Backend Administratora

Programowanie - wykład 4

Pętle. Dodał Administrator niedziela, 14 marzec :27

Arytmetyka liczb binarnych

Serwer WWW Apache. Plik konfiguracyjny httpd.conf Definiujemy m.in.: Aktualne wersje 2.4.6, , zakończony projekt

Języki i techniki programowania Ćwiczenia 2

Zatem w jaki sposób nasze programy mają komunikować się ze światem zewnętrznym?

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

PARADYGMATY I JĘZYKI PROGRAMOWANIA. Haskell. (w11)

SYSTEMY LICZBOWE 275,538 =

Programowanie komputerowe. Zajęcia 4

Wykład 8: klasy cz. 4

Metody numeryczne Laboratorium 2

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

JAVA?? to proste!! Autor: wojtekb111111

Programowanie funkcyjne (Haskell Wprowadzenie) Kowalik Adrian

Transkrypt:

HASKELL Higher order functions, Modules Janusz Bugajny Piotr Rogulski Łukasz Antoszkiewicz

Higher order functions Funkcje wyższego rzędu

Funkcja wyższego rzędu funkcja, która spełnia przynajmniej jeden z Przyjmuje jedną lub więcej funkcji jako parametr dwóch warunków: Zwraca funkcję

Funkcje wyższego rzędu są podstawowym elementem programowania funkcyjnego! Jeżeli chcemy definiowad tylko wynik działania naszego programu, a nie jego konkretne kroki i stany jak w tradycyjnym programowaniu, szybko przekonamy się, że funkcje wyższego rzędu są niezastąpione to technika bardzo przydatna w rozwiązywaniu problemów.

Curried functions Oficjalnie, każda funkcja w Haskellu przyjmuje tylko jeden parametr. Oczywiście programista może zdefiniowad funkcję z wieloma parametrami, ale wtedy pod spodem tworzy się tak naprawdę kilka funkcji, z których każda przyjmuje po jednym parametrze. Funkcje z więcej niż jednym parametrem to tzw. funkcje rozwijane curried functions. Termin ten pochodzi od nazwiska amerykaoskiego logika Haskella Curry ego (na jego cześd zostały też nazwane języki Haskell i Curry)

Curried functions - przykład Napiszmy prostą funkcję zwracającą iloczyn trzech liczb multthree :: ( Num a) => a -> a -> a -> a multthree x y z = x * y * z Pamiętajmy, że możemy wywoład metodę ze zbyt małą liczbą parametrów (uzyskujemy wtedy efekt podobny przeciążania metod albo ustalenia parametrów domyślnych w C++/Javie/C#) Zapis multthree 3 5 9 jest jednoznaczy z ((multthree 3) 5) 9 Na początku do funkcji jest przekazywana liczba 3. Tworzy to funkcję, która przyjmie jeden parametr i przemnoży go przez 3. Potem przekazywana jest 5. Ponownie tworzona jest funkcja, która przyjmuje jeden parametr i przemnoży go przez 15 (3*5). Do tej drugiej funkcji przekazywana jest 9 i zwrócony jest wynik 135.

Curried functions przykład c.d. Typ naszej funkcji równie dobrze więc mógłby byd zapisany w ten sposób: multthree :: ( Num a) => a -> (a -> (a -> a)) Przed każdym -> występuje typ przyjmowany, a po nim typ zwracany Nasza funkcja zatem przyjmuje jakiś typ liczbowy a i zwraca funkcję typu (Num a) =>a -> (a -> a). Analogicznie, ta funkcja bierze a i zwraca funkcję typu (Num a) =>a -> a. A ta ostatnia funkcja po prostu bierze a i zwraca a.

Curried functions przykład 2 Rozważmy prostą funkcję dzielenia liczby przez 10. dividebyten :: (Floating a) => a -> a dividebyten x = x/10 Okazuje się, że dokładnie ten sam efekt możemy osiągnąd nie podając w ogóle parametru do deklaracji funkcji dividebyten = (/10) Co to za czary?

Curried functions przykład 2 c.d. Otóż zapis (/10) zwraca nam nie liczbę, a funkcję dzielenia przez 10 Inaczej mówiąc, stworzyliśmy sobie nową funkcję dzielenia, w której po prawej stronie dzielnika będzie 10, a drugi argument jest dostarczany przy wowływaniu funkcji dividebyten. Main> dividebyten 35 3.5

Higher-orderism in action Funkcje mogą przyjmowad funkcje jako parametr i zwracad funkcje. Przykład: funkcja która przyjmuje funkcję i aplikuje ją dwukrotnie do czegoś applytwice :: (a -> a) -> a -> a applytwice f x = f (f x) Pierwszy parametr jest funkcją, która przyjmuje coś i zwraca ten sam typ (dlatego jest w nawiasach) Drugi parametr też musi byd tego samego typu, abyśmy mogli zaaplikowad do niego funkcję z pierwszego parametru Typ zwracany to również ten sam typ. *Main> applytwice (+10) 10 30

Higher-orderism c.d. funkcja zipwith Ciekawym przykładem jest standardowa funkcja zipwith zipwith ' :: (a -> b -> c) -> [a] -> [b] -> [c] zipwith ' _ [] _ = [] zipwith ' [] = [] zipwith ' f (x:xs) (y:ys) = f x y : zipwith ' f xs ys Pierwszym parametrem jest funkcja która dostaje dwa cosie i zwraca trzeci typ. Mogą to byd trzy te same typy, ale nie muszą. Jeśli w deklaracji mamy a -> b -> c, to zaakceptowana zostanie też funkcja typu a -> a -> a, ale nie odwrotnie! Drugi parametr to lista typu a, ponieważ funkcja łącząca przyjmuje a jako pierwszy parametr. Trzeci to lista b, ponieważ funkcja łącząca przyjmuje b jako drugi parametr. Rezultatem jest lista c.

zipwith przykłady użycia ghci > zipwith ' (+) [4,2,5,6] [2,6,2,3] [6,8,7,9] ghci > zipwith ' max [6,3,2,1] [7,3,1,5] [7,3,2,5] ghci > zipwith ' (++) ["foo ", " bar ", " baz "] [" fighters ", "hoppers "," aldrin "] [" foo fighters ","bar hoppers "," baz aldrin "] ghci > zipwith ' (*) ( replicate 5 2) [1..] [2,4,6,8,10] ghci > zipwith ' ( zipwith ' (*)) [[1,2,3],[3,5,6],[2,3,4]] [[3,2,2],[3,4,5],[5,4,3]] [[3,4,6],[9,20,30],[10,12,12]]

zipwith c.d. Jak widzimy, pojedyncza funkcja wyższego rzędu może mied bardzo wiele zastosowao. Programowanie funkcyjne używa funkcji wyższego rzędu aby wyabstrahowad od kontekstu typowe, często powtarzające się działania takie jak filtrowanie list, przetwarzanie ich elementów itp.

Map Funkcja map dostaje funkcję oraz listę i aplikuję tę funkcję do każdego elementu listy. map :: (a -> b) -> [a] -> [b] To samo można osiągnąd wyrażeniami lamba jednak przeważnie map jest znacznie czytelniejszy, szczególnie przy mapach map. ghci > map (+3) [1,5,3,1,6] [4,8,6,4,9] ghci > map (++ "!") [" BIFF ", " BANG ", " POW "] [" BIFF!"," BANG!","POW!"] ghci > map ( replicate 3) [3..6] [[3,3,3],[4,4,4],[5,5,5],[6,6,6]] ghci > map ( map (^2)) [[1,2],[3,4,5,6],[7,8]] [[1,4],[9,16,25,36],[49,64]] ghci > map fst [(1,2),(3,5),(6,3),(2,6),(2

Filter Funkcja filter bierze predykat (funkcja zwracająca prawdę lub fałsz) oraz listę i zwraca listę elementów spełniających ten warunek. filter :: (a -> Bool ) -> [a] -> [a] ghci > filter ( >3) [1,5,3,2,1,6,4,3,2,1] [5,6,4] ghci > filter (==3) [1,2,3,4,5] [3] ghci > filter even [1..10] [2,4,6,8,10]

takewhile Dostaje predykat i listę, a następnie zwraca elementy od początku listy dopóki predykat jest prawdziwy. takewhile :: (a -> Bool) -> [a] -> [a] *Main> takewhile (/=' ') "Ala ma kota" "Ala *Main> takewhile (<10) [1,2..100] [1,2,3,4,5,6,7,8,9] *Main> sum ( takewhile (<10000) [1,2..1000000] ) 49995000

Lambdy Lambdy to funkcje anonimowe, których używamy gdy potrzebujemy z danej funkcji skorzystad tylko raz. Z reguły piszemy je z celem podstawienia do funkcji wyższego rzędu Lambdę zapisujemy w następujący sposób: najpierw \, potem parametry, strzałka -> i ciało funkcji, całośd umieszczamy w nawiasach Prelude> let matrix = [ [1,2,3],[4,5,6],[7,8,9,0] ] Prelude> filter (\xs -> length xs > 3) matrix [[7,8,9,0]] Prelude> zipwith (\a b -> (a * 10 + b)) [5,4,3,2,1] [1,2,3,4,5] [51,42,33,24,15]

Folds Folds funkcje podobne do map, z tym, że redukują listę do pojedynczej wartości Funkcja typu fold przyjmuje funkcję binarną, jakąś wartośd startową (zwaną accumulatorem) i listę do zwinięcia. Funkcja binarna przyjmuje wartośd startową oraz pierwszy (lub ostatni) element z listy i zwraca nową wartośd accumulatora Potem funkcja jest wywoływana z accumulatorem i drugim w kolejności (lub przedostatnim) elementem listy itd. aż do przejścia całej listy. Przykład implementacji funkcji sumy z użyciem foldl (left fold)

Folds c.d. Podobnie działają funkcje foldl1 i foldr1 Różnica polega na tym, że nie podajemy w nich wartości początkowej Wartością początkową jest pierwszy (bądź ostatni) element listy Prelude> foldl1 (\x acc -> x - acc) [1,2,3,4,5] -13

Scans Scanl, scanr, scanl1, scanr1 funkcje podobne do foldów, z tym, że zwracają wszystkie kolejne wartości accumulatora w formie listy Prelude> scanl (\x acc -> x + acc) 0 [1,2,3,4,5] [0,1,3,6,10,15]

Kompozycja funkcji W matematyce kompozycja funkcji jest zdefiniowana w następujący sposób: co oznacza wywołanie funkcji f z rezultatem funkcji g. W Haskellu do tego służy operator. (.) :: (b -> c) -> (a -> b) -> a -> c f. g = \x -> f (g x) Zwródmy uwagę na typy. Funkcja f musi przyjmowad ten sam typ, który zwraca funkcja g. Więc funkcja wynikowa przyjmuje ten sam typ co g i zwraca typ zwracany przez f. Prelude> let f = negate. (^3) Prelude> f 20-8000

Moduły w Haskellu Moduł - jest to pewien zbiór powiązaznych ze sobą funkcji i klas. Program zaś jest kolekcją modułów. Dzięki podziałowi na moduły zyskujemy pewne rozgraniczenie funkcjonalności tzn. że poszczególne moduły dostarczają nam specyficzne funkcje przeznaczone do operowania na rożnego rodzaju danych. Moduły z reguły powinny być jaknajbardziej ogólne oraz luźno powiązane dzięki czemu zawarte w nich funkcjonalności można wykorzystac później w wielu programach (wielokrotne wykorzystanie kodu). Z drugiej jednak strony jeśli funkcje z poszczególnych modułów służą wspólnym celom (np. Do Manipulacji listami) są w pewien sposób odgórnie powiązane( ze wzgledu na przeznaczenie) jedna funkcjonalność z jednego modułu, dla konkretnego przypadku potrzebuje innej funkcjonalności z innego modułu. Standardowa biblioteka Haskella jest podzielona na moduły a każdy z nich zawiera funkcje i typy, które sa powiązane z innymi.

Importowanie modułu Aby zaimortować moduł wykorzysujemy komendę import np: import Data. List Takie użycie jest oczywiście rozpoznawane w środowisku GHCi, nie mniej jednak jest ono niezbędne i bardziej charakterystyczne podczas pisana skryptów umieszczonych w plikach, jeśli chcemy odwołać się do konkretnych funkcjonalności pochodzących z określonych modułów. Bardziej charakterystycznym dla środowiska GHCi jest dodawanie modułów za pośrednictwem komendy: :m <nazwa moudułu> np :m + Data. List, co nie zmienia faktu że jedna i druga komenda dodaje funkcje do globalnej przestrzeni nazw, przez to ich działanie staje się jednakowe.

Jeśli chcemy dodać kilka modułów możemy to zrobić poprzez pisanie ich w linij jeden po drugim: :m + Data. List Data. Map Data. Set itd. Jeśli używamy skryptu, który zawiera już wewnątrz zaimportowane moduły nie musimy tego robić z poziomu GHCi Aby opuścić poszczególny moduł używamy komendy: :m

Selekcja funkcjonalności zawartych w module Jeśli interesuje nas konkretna funkcja/funkcje pochodząca(e) z określonego modułu bez potrzeby jego całego ładowania wykorzystujemy konstrukcję typu: import Data. List ( nub, sort ) Jeśli zaś interesują nas wszystkie funkcje z wyjatkiem którejś korzystamy z konstrukcji: import Data. List hiding ( nub )

"Sposób na konflikty" Wyobraźmy sobie sytuację w której dwa moduły, z których korzystamy zawierają funkcje nazwane w ten sam sposób. Podczas jej wywołania Haskell "nie wie", z którego modułu funkcją ma do czynienia. Rozwiązaniem problemu jest zapis: import qualified nazwa_modułu dołączenie modułu nazwa_modulu.nazwa_funkcji użycie To samo w 'wersji skróconej': import qualified nazwa_modulu as nazwa_referencji nazwa_referencji.nazwa_funkcji

Data.List Moduł ten oczywiście (jak sama nazwa wskazuje) dostarcza typ Listowy oraz szereg operacji, których na tym typie bedziemy mogli używać. Intersperse Postępowanie Weź pewien element oraz listę. Umieść wspomniany element pomiędzy każdą parą elementów pochodzących z listy. Przykład: komenda: intersperse '.' "MONKEY" wynik:"m. O.N.K.E.Y " komenda: intersperse 0 [1,2,3,4,5,6] wynik:[1,0,2,0,3,0,4,0,5,0,6]

Data.List Transpose jest pewną odmianą permutacji Postępowanie Niech dana będzie pewna lista list. Weź element z pewnej listy będacej wewnątrz innej( stojący na odpowiedniej pozycji) i zestaw go z elementami, z inych list(będących wewnątrz tej samej listy) stojacymi na tej samej pozycji co on, tak aby powstał nowa lista.ponów działanie dla kolejnych elementów z określonych pozycji. Lepiej może widać to n aprzykładzie :) Przykład komenda: transpose [[1,2,3],[4,5,6],[7,8,9]] wynik: [[1,4,7],[2,5,8],[3,6,9]]

Data.List Intercalate jest pewną odmianą permutacji Postępowanie Weź listę (A) oraz listę list(b). Wstaw listę(a) pomiędzy pary list na liście list(b) utwórz nową listę powstałą na skutek tej operacji. Przykład komenda: intercalate " " [" hey "," there "," guys " ] wynik: " hey there guys "

Data.List Zadanie (transpose) Co zwróci poniższy zapis? transpose ["Op","lis","gjo","aek"]

Data.List concat Postępowanie Połącz elementy z listy list w jedną listę Przykład komenda: concat["za","gad","ka"] wynik: " zagadka"

Data.List??? Zagadka Mając daną listę list : [[1,4,7],[2,5],[3,6,8]] Przekształć ją do pojedyńczej listy postaci: [1,2,3,4,5,6,7,8].Jakich funkcji spośród pozananych należy użyć?

Data.List concatmap Postępowanie Zrób tosamo co Map :) i połącz listę list w jedną. A co robi map? Wykonuje dla wszystkich elementów listy operację podaną jako argument. Przykład komenda: concatmap(replicate 4)[[1,2],[3,4]] wynik: [[1,2],[1,2],[1,2],[1,2],[3,4],[3,4],[3,4],[3,4]] A co zwróciłby map?

Data.List and,or Postępowanie Weź wyrażenie logiczne i zwróc jego wynik=>true lub false. Końcowy wynik jest uzależniony od wartości true lub false dla poszczególnych elementów.tworzona jest tablica wartości logicznych. Przykłady komenda: and $ map ( >4) [5,6,7,8] wynik: True komenda: or $ map (==4) [2,3,4,5,6,1] wynik: True

Data.List Any,all Postępowanie Weź wyrażenie logiczne i sprawdź czy conajmniej jeden(any) lub wszystkie(all) elementy spełniają zapisany warunek. Przykłady komenda: any (==4) [2,3,5,6,1,4] wynik: True komenda: all (==4) [2,3,5,6,1,4] wynik: False

Data.List iterate Postępowanie Ustal wyrażenie i wartość początkową, od której zaczniesz je wykonywać.pamiętaj o ograniczeniu operacji, bo wpadniesz w petlę nieskończoną. Przykłady komenda: take 10 $ iterate (*3) 1 wynik: [1,3,9,27,81,243,729,2187,6561,19683] komenda: iterate (*3) 1 wynik: pętla nieskończona

Data.List Split Postępowanie Weź listę i liczbę, rozdziel listę na tyle elementów na ile wskazuje podana liczba. Przykłady komenda: splitat 3 " heyman " wynik: (" hey "," man " ) komenda: splitat ( -3) " heyman " wynik: (""," heyman " )

Data.List takewhile Postępowanie Wybierz elementy z listy spęłniające warunek. Działanie to wykonaj dla pojedyńczych egzemplaży w przypadku gdy istnieją powtórzenia. Przykłady komenda: takewhile ( >3) [6,5,4, 1] wynik: [6,5,4]

Data.List dropwhile Postępowanie Weź listę i usuń z niej elementy spełniające warunek. Działanie to wykonaj dla pojedyńczych egzemplaży w przypadku gdy istnieją powtórzenia. Przykłady komenda: dropwhile ( <3) [1,2,2,2,3,4,5,4,3,2,1] wynik: [3,4,5,4,3,2,1]

Data.List span Postępowanie Sprawdź warunek w span,dokonaj podziału. Przykłady komenda:span(/=4)[1,2,3,4,5,6,7] wynik: ([1,2,3],[4,5,6,7])

Data.List break Postępowanie Wykonaj z zaprzeczeniem warunek inaczej niż w span. Przykłady komenda:break (==4) [1,2,3,4,5,6,7] wynik: ([1,2,3],[4,5,6,7])

Data.List sort Postępowanie Sortuje listę w kolejności rosnącej Przykłady komenda:sort [8,5,3,2,1,6,4,2] wynik: [1,2,2,3,4,5,6,8]

Data.List group Postępowanie Utwórz grupy jednakowych elementów.z listy wybierz jednakowe elementy i umieść je w osobnych listach,utwórz listę list. Przykłady komenda: group [1,1,1,1,2,2,2,2,3,3,2,2,2,5] wynik: [[1,1,1,1],[2,2,2,2],[3,3],[2,2,2],[5]]

Data.List tails vs tail Postępowanie tails-weź listę, utwórz z niej podciągi ciągów(liste list) usuwając kolejno elementy z początku. tail-tworzy pojedyńczy podzbiór zbioru Przykłady komenda: tails[1,2,3,4] wynik: [[1,2,3,4],[2,3,4],[3,4],[4],[]] komenda: tail[1,2,3,4] wynik: [2,3,4]

Data.List inits Postępowanie Weź listę, utwórz z niej listy poprzez kolejne "odcinanie" jej elementów począwszy od piewrwszego.pierwszym elementem jest lista pusta. Przykłady komenda: inits[1,2,3,4] wynik: [[],[1],[1,2],[1,2,3],[1,2,3,4]] komenda:inits[1,2,3,4] wynik: [2,3,4]

Data.List Inne funkcje: IsPrefixOf IsSufixOf Elem NotElem Partition Find ElemIndex FindIndex FindIndices Zip4 ZipWith3

Data.List ZipWith4 Lines Unlines Words Delete Nub Union Intersect Index...

Data.Char Jest modułem, który dostarcza nam zbiór funkcjonalności, dzięki którym możemy przeprowadzać operacje na pojedyńczych symbolach. Daje nam to szerokie możliwości w kontekście przetwarzania ciągów znakowych(strings),gdyż są one poprostu listami symboli.

Data.Char Zbiór funkcji operujących na pojdyńczych symbolach i sprawdzających czy warunek z mimi związany jest prawdziwy bądź nie. iscontrol sprawdza czy symbol jest znakiem kontrolnym isspace sprawdza czy symbol jest białym znakiem islower sprawdza czy synbol jest napisany z małej litery isupper sprawdza czy synbol jest napisany z wielkiej litery isalpha sprawdza czy synbol jest literą czy cyfrą -cyfra(false) isalphanum sprawdza czy synbol jest literą czy cyfrą -cyfra(true) isprint sprawdza czy symbol ma możliwość wydrukowania(wypisania). isdigit sprawdza czy symbol jest cyfrą. isoctdigit sprawdza czy symbol jest zapisany w systemie

Data.Char ishexdigit sprawdza czy symbol jest zapisany w systemie szesnastkowym. isletter sprawdza czy symbol jest literą ismark sprawdza czy symbol posiada swój odpowiednik w Unicode isnumber sprawdza czy symbol jest cyfrą ispunctuation sprawdza czy symbol jest znakiem interpunkcyjnym issymbol sprawdza czy symbol jest znakiem matematycznym lub znakiem waluty

Data.Char isseparator sprawdza czy symbol jest separatorem bądź białym znakiem isascii sprawdza, czy symbol wpada do pierwszych 128 znaków z zestawu znaków Unicode. islatin1 sprawdza, czy bohater wpada do pierwszych 256 znaków z zestawu znaków Unicode. isasciiupper sprawdza czy symol jest 'wielkim' znakiem ASCII. isasciilower sprawdza czy symol jest 'małym' znakiem ASCII Ogólna sygnatura funkcji przyjmuje postać: Char -> Bool.

Data.Char words Postępowanie Weź ciąg znakowy i podziel go na podciągi w zależności od występowania białego znaku.na tej podstawie utwórz listę (lista string). Przykłady komenda: words "Ala ma kota" wynik:["ala","ma","kota"]

Data.Char Funkcje konwersji inttodigit,digittoint Postępowanie Weź typ wyjściowy i zamień go na inny. Przykłady komenda: map digittoint " 34538 " wynik:[3,4,5,3,8] komenda:inttodigit 5 wynik: '5' ograniczenie:zakres 1..15

Data.Char ord,chr Postępowanie Weź symbol i zamień go na jego cyfrowy odpowiednik (ord) i na odwrót(chr). Przykłady komenda:ord 'a' wynik: 97 komenda:chr 90 wynik: 'Z'

Data.Map Tablica asocjacyjna (tablica skojarzeniowa, mapa, słownik, ang. associative array, map, dictionary) nazwa dla powszechnie stosowanego w informatyce abstrakcyjnego typu danych, który przechowuje pary (unikatowy klucz, wartośd) i umożliwia dostęp do wartości poprzez podanie klucza.

W Haskell mapy dostępne są w module Data.Map, ich implementacja opiera się na drzewach, dlatego znalezienie wartości dla danego klucza odbywa się o wiele szybciej, niż w przypadku list, ponieważ w liście trzeba przechodzid wszystkie elementy, aż do momentu napotkania klucza Jeśli chcemy używad tego modułu musimy go zaimportowad import qualified Data.Map as Map

Tworzenie mapy Map.empty reprezentuje pustą mape let map = Map.empty Metoda fromlist przyjmuje liste i zwraca mape, jeśli w liście są powtórzenia, zostają one pominięte let map = Map.fromList [(1,21), (2,32), (3,5)]

Jeśli chcemy, by powtórzenia w liście nie były tylko pomijane, możemy użyd funkcji Map.fromListWith, która przyjmuje funkcje opisującą co ma zrobid, gdy napotka powtórzenie, oraz liste let mapa = Map.fromListWith (+) [(2,3),(2,5),(4,8)] Map.toList mapa Output: [(2,8), (4,8)] let mapa = Map.fromListWith (\x y -> y) [(1,2),(1,3),(2,4)] Map.toList mapa Output: [(1,3),(2,4)]

Wstawianie wartości do mapy Map.insert przyjmuje klucz, wartośd i mape, i zwraca nową mape utworzoną na podstawie przekazanej mapy, wraz z nowym elementem let mapa = Map.insert klucz wartosc Map.empty let mapa2 = Map.insert klucz2 wartosc2 mapa Map.insertWith analogiczna funkcja do Map.fromListWith

Usuwanie wartości z mapy Delete - przyjmuje klucz i mape, zwraca nową mape bez elementu, który znajdował się pod przekazanym kluczem let mapa = Map.fromList *(1, wartosc ),(2, wartosc )+ let mapa2 = Map.delete 2 mapa Map.toList mapa2 Output: *(1, wartosc )+

Map.member przyjmuje klucz i mape, zwraca wartośd logiczną czy mapa zawiera dany klucz Map.member 3 $ Map.fromList [(3,6),(4,3),(6,9)] Output: True Map.lookup przyjmuje klucz i mape, zwraca wartośd przypisaną do klucza let mymap = Map.fromList[(3,6),(4,2)] Map.lookup 3 mymap Output: Just 6

Map.size przyjmuje mape i zwraca ilośd jej elementów let mymap = Map.fromList [(1,2),(2,3)] Map.size mymap Output: 2 Map.null przyjmuje mape i zwraca wartośd logiczną czy mapa jest nullem Map.null mymap Output: False

Map.map pozwala modyfikowad całą mape w określony sposób let mymap = Map.map (*100) $ Map.fromList[(1,1),(2,4),(3,9)] w tym przypadku wszystkie wartości zostaną pomnożone * 100, mapa będzie wyglądad następująco: [(1,100),(2,400),(3,900)]

Map.keys przyjmuje mape i zwraca wszystkie klucze w niej zawarte Map.keys Map.fromList [(1,21),(2,22),(2,13)] Output:[1,2,3] Map.elems przyjmuje mape i zwraca wszystkie jej wartości

Data.Set Data.Set jest to moduł oferujący nam strukture danych, w której każdy element jest unikalny. Można wykonywad na nim takie operacje m.in. jak, wstawianie, usuwanie, sprawdzanie czy coś należy już do setu oraz konwersje do listy. Jego implementacja oparta jest na drzewach Aby używad tego modułu musimy dokonad importu: import qualified Data.Set as Set

Tworzenie Setu fromlist przyjmuje liste, a zwraca set let myset = Set.fromList przykladowy tekst Po wypisaniu zawartości tego setu, zobaczymy: Output: adekloprstwyz Widzimy, że wartości setu są unikalne i posortowane

Intersection funkcja przyjmuje dwa sety, i zwraca ich częśd wspólną let set1 = Set.fromList abcdefgh let set2 = Set.fromList azcdefgk Set.intersection set1 set Output: acdefg Difference funkcja przyjmuje dwa sety, i zwraca elementy które są w pierwszym secie, ale nie ma ich w drugim Set.difference set1 set2 Output: bh

Union funkcja przyjmuje dwa sety, i zwraca set ze wszystkimi elementami pierwszego i drugiego setu let set1 = Set.fromList abcdefgh let set2 = Set.fromList azcdefgk Set.union set1 set2 Output: abcdefghkz

Moduł Data.Set oferuje nam jeszcze funkcje null, size, member, empty, insert, delete, tolist działające analogicznie jak w module Data.Map Sety są często używane do wyodrębnienia powtórzeo z listy poprzez zamiane listy na set, a później z powrotem na liste. Funkcja nub z Data.List robi tą czynnośd, jednak zamiana na set i z powrotem, działa o wiele szybciej, co przy dużej liście, może byd istotne.

Moduły Moduł - jest to pewien zbiór powiązanych ze sobą funkcji i klas. Program zaś jest kolekcją modułów. Dzięki podziałowi na moduły zyskujemy pewne rozgraniczenie funkcjonalności tzn. że poszczególne moduły dostarczają nam specyficzne funkcje przeznaczone do operowania na rożnego rodzaju danych. Moduły pozwalają nam na to, że raz napisane funkcje, czy definicje typów, łatwo używad w innych programach, bo wystarczy dany moduł zaimportowad.

Tworzenie swojego modułu Moduły zapisujemy w plikach o rozszerzeniu.hs Nazwa modułu powinna byd taka sama jak pliku Moduł powinniśmy przechowywad w folderze o takiej samej nazwie jak nazwa modułu Szkielet modułu: module Nazwa ( -- metody danego modułu ) where --definicje metod

Przykładowy moduł module Geometria ( polekwadratu, obwodkwadratu, poleokregu, obwodokregu ) where polekwadratu :: Float -> Float polekwadratu bok = bok * bok obwodkwadratu :: Float -> Float obwodkwadratu bok = bok * 4 poleokregu :: Float -> Float poleokregu promien = pi * (promien^2) obwodokregu :: Float -> Float obwodokregu promien = 2 * pi * promien

Jeśli chcemy, aby nasz moduł opisywał tylko konkretną figurę, wtedy jeden duży moduł można napisad w postaci podmodułów. module Geometria.Kwadrat ( pole, obwod )where pole :: Float -> Float pole bok = bok * bok obwod :: Float -> Float obwod bok = bok * 4

module Geometria.Okrag ( pole, obwod )where pole :: Float -> Float pole promien = pi * (promien^2) obwod :: Float -> Float obwod promien = 2 * pi * promien Moduły powinniśmy móc użyd w następujący sposób: - ścieżkę pracy programu powinniśmy mied na tym samym poziomie co folder, w którym znajduje się nasz moduł, a następnie poleceniem: import Geometria.Kwadrat, zaimportowad moduł. Gdybyśmy chcieli używad kilka modułów naraz to musimy użyd polecenia import qualified import qualified Geometria.Kwadrat as Kwadrat import qualified Geometria.Okrag as Okrag

Wkorzystane materiały: Learn You a Haskell for Great Good! Miran Lipovaca