Języki i Paradygmaty Programowania

Podobne dokumenty
- nawiasy kwadratowe oznaczają, że to lista

Wstęp do Programowania potok funkcyjny

Podstawy programowania funkcjonalnego

Wstęp do Programowania potok funkcyjny

Programowanie funkcyjne (Haskell Wprowadzenie) Kowalik Adrian

Prezentacja o Haskell u(rozdział 3 i 4)

Elementy języka Haskell

Leży u podstaw programowania funkcyjnego. Napisy. 1 Zastapienie dowolnego wyrażenia innym wyrażeniem o tej samej. wartości daje równoważny program.

Programowanie Funkcyjne. Marcin Kubica Świder,

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

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

MATERIAŁY DO ZAJĘĆ II

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

Składnia funkcji i Rekurencja w języku Haskell

Microsoft IT Academy kurs programowania

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Ćwiczenia z wyliczania wartości funkcji

4. Funkcje. Przykłady

Języki programowania Haskell

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

Haskell Moduły Ładowanie

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

Wstęp do programowania

Programowanie Obiektowe i C++

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

Wstęp do programowania

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

Podstawy programowania w języku C i C++

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

29. Poprawność składniowa i strukturalna dokumentu XML

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

PARADYGMATY PROGRAMOWANIA Wykład 3

Język programowania Scala / Grzegorz Balcerek. Wyd. 2. Poznań, cop Spis treści

Programowanie obiektowe i C++ dla matematyków

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Nazwa pochodzi od imienia znanego logika Haskell a Brooks a Curry ego ( )

Paradygmaty programowania

λ parametry. wartość funkcji suma = λ x y. x + y kwadrat = λ x. x * x K.M. Ocetkiewicz, 2008 WETI, PG 2 K.M. Ocetkiewicz, 2008 WETI, PG 3

Język ludzki kod maszynowy

Podstawy i języki programowania

Wstęp do programowania. Różne różności

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

Wprowadzenie do języka Java

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Podstawy i języki programowania

INSTRUKCJA PUSTA. Nie składa się z żadnych znaków i symboli, niczego nie robi. for i := 1 to 10 do {tu nic nie ma};

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

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

Wstęp do Programowania 2

Odczyt danych z klawiatury Operatory w Javie

DIAGRAMY SYNTAKTYCZNE JĘZYKA TURBO PASCAL 6.0

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Algorytmika i Programowanie VBA 1 - podstawy

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Programowanie obiektowe

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

Wstęp do programowania

Programowanie Komputerów

Semantyka i Weryfikacja Programów - Laboratorium 3

Zmienne, stałe i operatory

1 Podstawy c++ w pigułce.

Programowanie w Ruby

Informatyka 1. Wyrażenia i instrukcje, złożoność obliczeniowa

Programowanie obiektowe

R. D. Tennent, The Denotational Semantics of Programming Languages [1976]

ECDL Podstawy programowania Sylabus - wersja 1.0

Programowanie w C++ Wykład 3. Katarzyna Grzelak. 12 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 35

Zadanie 04 Ktory z ponizszych typow danych w jezyku ANSI C jest typem zmiennoprzecinkowym pojedynczej precyzji?

Podstawy Programowania.

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

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

Część 4 życie programu

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

HASKELL 2 R O Z D Z I A Ł 4 SKŁADNIA W FUNKCJACH R O Z D Z I A Ł 5 REKURENCJA. Learn You a Haskell for Great Good! Miran Lipovac

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

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

Programowanie Obiektowe i C++

Wstęp do informatyki. stęp do informatyki Polecenia (cz.2)

Functionalization. Funkcje w C. Marcin Makowski. 30 listopada Zak lad Chemii Teoretycznej UJ

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

Języki programowania Prolog

Odwrotna Notacja Polska

PL/SQL. Część 1 Bloki PL/SQL. Piotr Medoń

Wykład 11a. Składnia języka Klasycznego Rachunku Predykatów. Języki pierwszego rzędu.

dr inż. Jarosław Forenc

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Wstęp do Programowania, laboratorium 02

Informatyka 1. Przetwarzanie tekstów

1 Podstawy c++ w pigułce.

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

Bash - wprowadzenie. Bash - wprowadzenie 1/39

JavaScript funkcyjność

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

SQL, LIKE, IN, CASE, EXISTS. Marcin Orchel

Przydatne sztuczki - sql. Na przykładzie postgres a.

typ zakres sposob zapamietania shortint integer bajty (z bitem znaku) longint byte word

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

Wstęp do Programowania potok funkcyjny

Transkrypt:

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/ :? for help Prelude> 2 ^ 100 1267650600228229401496703205376 Prelude> words "Ala ma kota" ["Ala","ma","kota"] Prelude> :type words words :: String -> [String] Listy [ ] lista pusta x : xs lista o głowie x i ogonie xs Prelude> [1,2,3] [1,2,3] Prelude> [4] ++ [5,6] [4,5,6] Prelude> 1:[] [1] Prelude> [0..9] [0,1,2,3,4,5,6,7,8,9] Prelude> [1,3..10] [1,3,5,7,9] Prelude> take 4 [0..9] [0,1,2,3] 1

Napisy Napisy sa listami znaków Prelude> "napis" "napis" Prelude> [ H, a, s, k, e, l, l ] "Haskell" Prelude> unwords ["hello","world"] "hello world" NB w razie potrzeby, istnieja bardziej efektywne implementacje, np. Data.Text, Data.ByteString. Wycinanki listowe W matematyce często tworzymy zbiory przy pomocy aksjomatu wycinania: {3x x {1,..., 10}, x mod 2 = 1} Podobnie możemy tworzyć listy w Haskellu: > [3*x x <- [1..10], mod x 2 == 1] [3,9,15,21,27] x<-[1..10] jest generatorem mod x 2 == 1 jest filtrem. Możemy tworzyć wycinanki o większej liczbie generatorów i filtrów, np. > [(x,y) x<-[1..5],y<-[1,2,3],x+y == 5,x*y == 6] [(2,3),(3,2)] Definiowanie funkcji Stwórzmy plik e01.hs mul x y = x * y square x = mul x x area r = pi * square r teraz $ ghci e01.hs... Ok, modules loaded: Main. *Main> area 1 3.141592653589793 *Main> area 2 12.566370614359172 2

Program obowiazkowy: silnia fact1 n = if(n <= 0) then 1 else n*fact1(n-1) W Haskellu mozemy to zapisać także tak: fact2 n n <= 1 = 1 otherwise = n*fact2(n-1) Silnia na N sposobów Silnia na N sposobów: tinyurl.com/silnian Definicje przez przypadki (dopasowanie) Jak obliczyć długość listy? 1 o lista pusta ([ ]) 0 2 o lista niepusta (h:t) 1 + długość t len [] = 0 len (h:t) = 1 + len t Takie definicje rekurencyjne spotykamy często zarówno w matematyce i w Haskellu. Także silnię możemy zdefiniować w ten sposób: fact3 0 = 1 fact3 n = n * fact3 (n-1) Typy Każda wartość ma swój typ (intuicyjnie możemy mysleć o typach jako o zbiorach wartości), np: True :: Bool 5 :: Int a :: Char [1, 4, 9] :: [Int] -- lista "hello" :: String -- (String = [Char]) ("ala",4) :: (String, Int) -- para Funkcje oczywiście też maja typy: isdivby :: Int -> Int -> Bool isdivby x y = mod x y == 0 W większości wypadków Haskell potrafi sprawdzić poprawność typów bez żadnych deklaracji (rekonstruuje typy) 3

Podstawowe typy Int maszynowe liczby całkowite Integer liczby całkowite dowolnej precyzji Char znaki (Unicode) String napisy (Unicode) Maybe: jeśli a jest typem, to Maybe a jest typem Nothing::Maybe a jeśli x::a to (Just x)::maybe a Listy: [a] jest lista elementów typu a []::[a] jeśli x::a oraz xs::[a], to (x:xs)::[a] Krotki: (a 1,..., a n ) jest produktem kartezjańskim typów a 1,..., a n W szczególności () jest typem zawierajacym jeden element: ()::() Wyrażenia Podstawowe rodzaje wyrażeń w Haskellu to: literały, np. 42, "Foo"; zmienne, np. x (musza być z małej litery); zastosowanie funkcji do argumentu, np. succ 9; zastosowanie operatora infiksowego, np. x + 1; wyrażenie if e then e else e ; wyrażenie case (analiza przypadków); wyrażenie let (lokalna deklaracja); wyrażenie λ (funkcja anonimowa). konstruktory (na kolejnym wykładzie) 4

Wyrażenie case Wyrażenie if jest lukrem syntaktycznym dla case: if e then e else e jest tłumaczone do case e of { True -> e ; False -> e } W ogólności case ma postać case e of { wzorzec1 -> e1;...; wzorzec_n -> e_n }... i oznacza: przeanalizuj wyrażenie e i w zalezności od tego, do którego z wzorców pasuje, daj odpowiedni wynik Układ czyli wcięcia maja znaczenie Nawiasy klamrowe i średniki możemy pominać, jeśli użyjemy odpowiednich wcięć w programie: case e of True -> wyrazenie ew. dalszy ciąg wyrażenia bardziej wcięty False -> nastepny przypadek tak samo wcięty Używanie układu nie jest obowiazkowe jeśli użyjemy nawiasów i średników, możemy wcinać dowolnie. Układ jest dopuszczalny także w innych konstrukcjach, takich jak let, do, where, itp. Definicje Program (a ściślej moduł) w Haskellu jest zbiorem definicji funkcji, typów i klas. Kolejność tych definicji nie ma znaczenia. Definicja funkcji składa się z (opcjonalnej) sygnatury typu i ciagu równań (dla różnych przypadków tu kolejność ma znaczenie). Równania moga być rekurencyjne, moga też używać innych funkcji, także tych zdefiniowanych niżej. f :: Int -> Int f 0 = 1 f n = n * g(n-1) g n = n * f(n-1) g 0 = 1 5

Kolejność równań f :: Int -> Int f 0 = 1 f n = n * f(n-1) g n = n * g(n-1) g 0 = 1 kolejnoscrownan.hs:5:0: Warning: Pattern match(es) are overlapped In the definition of g : g 0 =... Ok, modules loaded: Main. *Main> f 5 120 *Main> g 5 *** Exception: stack overflow *Main> Dopasowywanie wzorców Wzorce moga być bardziej złożone, np third :: [a] -> a third (x:y:z:_) = z (podkreślenie oznacza cokolwiek ) Równanie moze też wymagać dopasowania więcej niż jednego argumentu: myzip :: [a] -> [b] -> [(a,b)] myzip (x:xs) (y:ys) = (x,y):myzip xs ys myzip = [] Dopasowanie wzorców działa w równaniach podobnie jak w case (i innych miejscach), poza tym, że w case oczywiście dopasowujemy tylko jedno wyrażenie. Wyrażenie let Wyrażenie let pozwala nam na użycie lokalnych definicji pomocniczych dla obliczenia jakiegoś wyrazenia: let { definicja1;...; definicja_n } in e Tak jak przy case możemy uzyć wcięć zamiast nawiasów i średników, np. let x = 1 y = 2 in x + y 6

a nawet let answer = 42 in answer Definicje w let moga być wzajemnie zależne (tak jak na najwyższym poziomie). Wyrażenie let W wyrażeniu let możemy definiować funkcje, używać rekurencji i dopasowań: f xs = let len [] = 0 len (x:xs) = 1 + len xs in len xs Uwaga: reguły wcinania wymagaja aby w tym wypadku: len było bardziej wcięte niż linia, w której zaczyna się let (czy f) oba równania dla len były tak samo wcięte in było wcięte mniej niż len, ale bardziej niż f (oczywiście jeśli uzywamy { ; } mozemy wcinać dowolnie). Wyrażenie λ Wyrażenie λ pozwala na skonstruowanie i użycie w wyrażeniu funkcji anonimowej (jak w rachunku lambda). Tekstowo lambdę zapisujemy jako backslash (\x -> x + 1) 9 10 Możemy używać dopasowania wzorca (ale tylko jeden przypadek): pierwszy = \(x,y) -> x Może być więcej niż jeden argument: (\x y -> x) 1 2 oznacza to samo co (\x -> (\y -> x)) 1 2 7

Podprzypadki Zadanie: podzielić listę na dwie: elementy n oraz > n splitby :: Int -> [Int] -> ([Int],[Int]) splitby n [] = ([],[]) splitby n (x:xs) = let (ys,zs) = splitby n xs in if x<= n then (x:ys,zs) else (ys,x:zs) Drugi przypadek naturalnie dzieli sie na dwa podprzypadki; nie możemy tego zapisać przez wzorce, ale możemy tak: splitby n (x:xs) x<=n = let (ys,zs)=splitby n xs in (x:ys,zs) x>n = let (ys,zs)=splitby n xs in (ys,x:zs) Klauzula where splitby n (x:xs) x<=n = let (ys,zs)=splitby n xs in (x:ys,zs) x>n = let (ys,zs)=splitby n xs in (ys,x:zs) W obu przypadkach powtarza się ta sama definicja, możemy to krócej zapisać: splitby n (x:xs) x<=n = (x:ys,zs) otherwise = (ys,x:zs) where (ys,zs) = splitby n xs where jest poniekad podobne do let, ale let jest wyrażeniem, where jest częścia definicji Zasięgiem definicji w let jest wyrażenie po in; zasięgiem definicji w where całe równanie Operatory infiksowe Nazwy złożone z symboli domyślnie sa używane w składni infiksowej: xs ++ ys to to samo co (++) xs ys. Ujęcie operatora w nawiasy odbiera mu infiksowość. Podobnie ujęcie nazwy prefiksowej (z liter i cyfr) w odwrócone apostrofy nadaje jej infiksowość : x mod 2 Operatory nie sa magiczne, możemy definiować własne: infixl 6 +++ (+++) :: Int -> Int -> Int x +++ y = (x+y)*(x+y+1) div 2 8

Deklaracja infixl... oznacza, że +++ wiaże w lewo i ma priorytet 6 (taki sam jak +) Niektóre ciagi symboli sa zastrzeżone:.. :: = \ <- -> @ ~ => -- (lub więcej -) rozpoczyna komentarz, ale np +-- ani --+ nie Jeszcze o priorytetach Minusa unarnego nie należy mieszać z operatorami infiksowymi: Prelude> 2 * -3 Precedence parsing error cannot mix * [infixl 7] and prefix -... Prelude> 2 * (-3) -6 Prefiksowa aplikacja funkcji ma wyższy priorytet niż operatory infiksowe; wiaże w lewo, czyli f x y oznacza (f x) y Z kolei ($) jest operatorem aplikacji funkcji o priorytecie 0, wiaż acym w prawo, co pozwala oszczędzić nawiasów i napisać np. length $ show $ foldl (*) 1 [1..1000] zamiast length ( show ( foldl (*) 1 [1..1000] ))...chociaż prawdopoodobnie ta druga notacja jest dle wielu osób czytelniejsza; Haskell kładzie jednak nacisk na zwięzłość. Przekroje Operatory infiksowe sa z natury swej dwuargumentowe. Podajac operatorowi jeden z argumentów mozemy uzyskać funkcję jednoargumentowa. Konstrukcja taka nazywa się przekrojem (section) operatora. Prelude> (+1) 2 3 Prelude> (1+) 3 4 Prelude> (0-) 4-4 Przekrojów używamy przeważnie, gdy chcemy taka funkcję przekazać do innej funkcji. 9