PARADYGMATY I JĘZYKI PROGRAMOWANIA. Przegląd języków funkcyjnych (w10)



Podobne dokumenty
Elementy języka Scheme

Elementy języka Scheme

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

Definicje wyższego poziomu

Podstawy programowania funkcjonalnego

Języki programowania Haskell

Programowanie funkcyjne (Haskell Wprowadzenie) Kowalik Adrian

Paradygmaty programowania

Paradygmaty programowania

Ćwiczenia z wyliczania wartości funkcji

Programowanie Funkcyjne. Marcin Kubica Świder,

- nawiasy kwadratowe oznaczają, że to lista

λ 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

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

Programowanie obiektowe

Wstęp do programowania

Języki i Paradygmaty Programowania

Wykład 0 Informacje Podstawowe

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

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

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

Przyszłość programowania Języki funkcyjne na przykładzie Clojure

Składnia funkcji i Rekurencja w języku Haskell

Elementy języka Haskell

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

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

Microsoft IT Academy kurs programowania

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

Wstęp do Programowania potok funkcyjny

JavaScript funkcyjność

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Technologie cyfrowe semestr letni 2018/2019

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

Prezentacja o Haskell u(rozdział 3 i 4)

LISP - "LISt Processing"

Technologie cyfrowe semestr letni 2018/2019

KOTLIN. Język programowania dla Androida

Programowanie strukturalne. Opis ogólny programu w Turbo Pascalu

Funkcje w PL/SQL Funkcja to nazwany blok języka PL/SQL. Jest przechowywana w bazie i musi zwracać wynik. Z reguły, funkcji utworzonych w PL/SQL-u

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

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

Języki programowania deklaratywnego

PARADYGMATY I JĘZYKI PROGRAMOWANIA. Programowanie funkcyjne (w- 9)

Wykład 4. Algorytmy i programy. Algorytmy + struktury danych = programy. Niklaus Wirth. Algorytm = logika + sterowanie.

1 Podstawy c++ w pigułce.

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

Programowanie funkcyjne. Wykªad 13

4. Funkcje. Przykłady

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

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

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

Podstawowe części projektu w Javie

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Wstęp do programowania

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

Programowanie - instrukcje sterujące

Bloki anonimowe w PL/SQL

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

Zofia Kruczkiewicz, Programowanie obiektowe - java, wykład 2 1

Podstawy Programowania ELEMENTY PROGRAMU i TYPY DANYCH

Wstęp do programowania

1 Podstawy c++ w pigułce.

ALGORYTMY I STRUKTURY DANYCH

Jerzy Nawrocki, Wprowadzenie do informatyki

Podstawy Programowania C++

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk

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

Politechnika Krakowska im. Tadeusza Kościuszki. Karta przedmiotu. obowiązuje studentów rozpoczynających studia w roku akademickim 2015/2016

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Programowanie - wykład 4

Klasa 2 INFORMATYKA. dla szkół ponadgimnazjalnych zakres rozszerzony. Założone osiągnięcia ucznia wymagania edukacyjne na. poszczególne oceny

Język programowania PASCAL

Bash - wprowadzenie. Bash - wprowadzenie 1/39

Komentarze w PHP (niewykonywane fragmenty tekstowe, będące informacją dla programisty)

Python wprowadzenie. Warszawa, 24 marca PROGRAMOWANIE I SZKOLENIA

Wstęp do programowania

Wstęp do informatyki

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

Zapisywanie algorytmów w języku programowania

Wstęp do programowania

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Paradygmaty programowania

PODSTAWY BAZ DANYCH 13. PL/SQL

Redis, skrypty w języku Lua

Języki i paradygmaty programowania. I. Wprowadzenie

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

Rekurencja (rekursja)

Języki formalne i techniki translacji

Programowanie komputerowe. Zajęcia 2

ForPascal Interpreter języka Pascal

PODSTAWY INFORMATYKI 1 PRACOWNIA NR 6

20. Pascal i łączenie podprogramów Pascala z programem napisanym w C

Język skryptowy: Laboratorium 1. Wprowadzenie do języka Python

Informatyka II stopień (I stopień / II stopień) Ogólnoakademicki (ogólno akademicki / praktyczny) Kierunkowy (podstawowy / kierunkowy / inny HES)

Programowanie funkcyjne Wykład 13. Siła wyrazu rachunku lambda

Programowanie obiektowo zorientowane. Mirosław Głowacki Wykład w języku C++

Podstawy programowania C. dr. Krystyna Łapin

Transkrypt:

PARADYGMATY I JĘZYKI PROGRAMOWANIA Przegląd języków funkcyjnych (w10)

Treść 2 Przegląd języków funkcyjnych LISP i SCHEME (DrRacket) n podstawy n listy, reprezentacja list, operacje na listach n funkcje wbudowane Haskell, ghc, ghci

3 LISP i SCHEME Krótkie wprowadzenie

Historia 4 Jest to pierwszy język funkcyjny John McCarthy, MIT, 1959 Pierwsza implementacja: komputer IBM704 Następne: SCHEME (Racket: h_p://racket- lang.org) dialekt Opis: Dybvig, 2003 Dostępność Sussman, Steele, MIT, 1975 Interpreter REPL (read- evaluate- print loop); używany też w Ruby, Python

Charakterystyka ogólna 5 Jednorodność (homogeniczność) danych i programu wszystko jest listą; operacje na danych i programie wykonywane są wg. tego samego schematu, z użyciem tych samych narzędzi Język samodefiniujący się semantykę Lispa można zdefiniować z pomocą interpretera Lispa pętla read- eval- print pozwala na interakcję między programem a użytkownikiem

Proste przykłady 6 (+ 3 4) 7 7 7 (load program ) ((+ 3 4)) eval: 7 is not a procedure (+ 3 4) 7 ((+ 3 4)) błąd Predykaty (boolean?? a) (char? a) (string? a) (symbol? a) (number? a) (pair? a) (list? a) ;czy a jest Boolean? ;czy a jest znakiem? ;czy a jest napisem? Cytowanie: (quote (+ 3 4)) (+ 3 4) Typowanie dynamiczne (if (> a 0) (+ 2 3) (+ 2 nic )) Jeśli a jest dodatnie 5 Jeśli a<=0 błąd Symbol odpowiada nazwie w innych językach. Funkcja lambda (lambda (x) (* x x)) Pierwszy argument funkcji lambda jest listą formalnych argumentów (tutaj x), a pozostałe tworzą ciało funkcji (tutaj (* x x)) Obliczanie funkcji lambda: ((lambda (x) (* x x)) 7) 49

Proste przykłady 7 Nazwy można związać z wartościami poprzez zakresy zagnieżdżone używając konstrukcji let: (let ((a 3) (b 4) (kwadrat (lambda (x) (* x x))) (plus +)) (sqrt (plus (kwadrat a) (kwadrat b))) ) 5 let posiada dwa argumenty: pierwszy zawiera pary nazwa- wartość (np. (a 3)), a drugi jest wartością wyrażenia (zielony). Zakresem wszystkich zmiennych jest tylko drugi argument let. Wiązania dotyczą nie tylko zmiennych w zwykłym sensie ale też funkcji, np. plus, kwadrat. (let ((a 3) (let ((a 4) (b a)) (+ a b))) 7 Tutaj, b przyjmuje wartość zewnętrznego a (a więc 3). Sposób w jaki nazwy stają się widoczne wszystkie jednocześnie na końcu listy deklaracji, nie pozwala na definicje rekurencyjne. Do tego celu służy letrec: (letrec ((fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1))))))) (fact 4)) 24 Scheme jest językiem o zakresach statycznych. let i letrec nie zmieniają znaczeń globalnych. Globalne nazwy definiuje się używając define (efekty uboczne): (letrec (p_prost (lambda (a b) (sqrt (+ (* a a) (* b b))))) (p_prost 3 4) 5

Typy 8 Dwa typy danych atomy listy n elementami list są pary n pierwszy element pary jest wskaźnikiem do atomu lub listy n drugi element pary jest wskaźnikiem do innego elementu lub wskaźnikiem do listy pustej n Elementy list są łączone za pomocą drugiego elementu pary Nie są to typy w sensie języków imperatywnych

Operacje podstawowe 9 Dane literalne oznaczane są przez QUOTE (cytowania) (QUOTE A) A (QUOTE (A B C)) (A B C) W skrócie QUOTE = (apostrof); np. (A B); Zapis taki (w językach LISP- podobnych jest konieczny z tego powodu, że kod i dane mają taką samą postać Operacje podstawowe na listach: CAR, CDR, CONS CAR = contents of the adress part of a register; CDR = contents of decrement part of the register nazwy części rejestru komputera IBM 704 na którym pierwszy raz implementowano LISP

Operacje podstawowe 10 Przykłady (CAR (A B C)) A (CAR ((A B) C D)) (A B) (CAR A) błąd, A nie jest listą (CAR ()) błąd (CDR (A B C)) (B C) (CDR (A)) () (CDR ()) błąd

Operacje podstawowe 11 ZŁożenia operacji (CAAR (...)) == (CAR (CAR (...)) (CADR (...)) == (CAR (CDR (...)) (CADDAR (...)) == (CAR (CDR (CDR (CAR (...)) " CONS (CONS A ()) (A) (CONS A (B C)) (A B C) (CONS () (A B)) (() A B) (CONS (A B) (C D)) ((A B) C D) (CONS (CAR lista) (CDR lista)) lista

Operacje podstawowe 12 Para niewłaściwa (CONS A B) (A. B) LIST (LIST X Y Z) (X Y Z) to samo (CONS X (CONS Y (CONS Z ()))) (X Y Z) Predykaty EQ?, EQV?, NULL?, LIST?,...

Reprezentacja list 13 Lista (A B C D)! A B C D D A B C E Lista: (A (B C) D (E F G)))! F G

Funkcje 14 Notacja polska (Jan Łukasiewicz, 1920) (+ 2 3), (* 1 3 5 7) funkcja lambda (nazwa (lambda (arg1...argn) wyr.)" EVAL funkcja obliczania wszystkiego; interpreter LISPA Zakresy dynamiczne od początku; obecnie (np. SCHEME): stat dyn (oba do wyboru)"

Predykaty, sterowanie 15 =, <>, >, <, >=, <=, EVEN?, ODD?, ZERO?,... " #T, #F wartości logiczne NOT, AND, OR" Sterowanie schemat: (IF predykat wyrażenie_then wyrażenie_else)" Przykład (DEFUN LISP; DEFINE SCHEME) (DEFUN (silnia n) (IF (<= n 1) 1 (* n (silnia (- n 1))) ) "

Sterowanie 16 COND (cond ((< 3 2) 1) ((< 4 3) 2) (else 3)) 3" Argumentami cond są pary, które obliczane są w kolejności wystąpienia. Wartością całego wyrażenia jest wartość drugiego elementu tej pary, która rozwija się do #t (true). Symbolu else można użyć tylko w ostatniej parze (oznacza wówczas #t).

Iteracje 17 Iteracje zapewnia specjalna postać do i funkcja foreach: (define iter-fibo (lambda (n) ; drukuje n liczb Fibonacciego (do ((i 0 (+ i 1)) ; pocz. 0, nast. +1 (a 0 b) ; pocz. 0, nast. b (b 1 (+ a b))) ; pocz. 1; suma a, b ((= i n) b) ; test konca; wartosc (display b) ; wnętrze pętli (display )))) ; wnętrze pętli

Przykład definicji funkcji 18 LISP (DEFUN (przestepny? rok) (COND ((ZERO? (MODULO rok 400)) #T) ((ZERO? (MODULO rok 100)) #F) (ELSE (ZERO? (MODULO rok 4))) )) "

Kolejność obliczania 19 tryb aplikacyjny argumenty są obliczane przed przekazaniem do funkcji lub z funkcji tryb normalny przekazywane są nieobliczone argumenty Przykład (Sco_): (define double (lambda (x) (+ x x))) tryb aplikacyjny (double (* 3 4)) (double 12) (+ 12 12) 24 tryb normalny (double (* 3 4)) (+ (* 3 4) (* 3 4)) (+ 12 (* 3 4)) (+ 12 12) 24 W trybie normalnym wykonuje się dwa razy obliczanie (* 3 4) W innych przypadkach może być odwrotnie (patrz: następna strona)

Kolejność obliczania 20 Przykład (Sco_) tryb normalny (define switch (lambda (x a b c) (cond ((< x 0) a) ((= x 0) b) ((> x 0) c)))) tryb aplikacyjny (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) (switch -1 3 (+ 2 3) (+ 3 4)) (switch -1 3 5 (+ 3 4)) (switch -1 3 5 7) (cond ((< -1 0) 3) ((= -1 0) 5) (cond (#t 3) 3 ((> -1 0) 7)) ((= -1 0) 5) ((> -1 0) 7)) (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) (cond ((< -1 0) (+ 1 2)) ((= -1 0) (+ 2 3)) ((> -1 0) (+ 3 4))) (cond (#t (+ 1 2)) (+ 1 2) 3 ((= -1 0) (+ 2 3)) ((> -1 0) (+ 3 4))) W trybie normalnym nie są obliczane wyrażenia (+ 2 3), (+ 3 4) W obu trybach istnieją wyjątki. W takich specjalnych wyrażeniach jak cond funkcje arytmetyczne i logiczne (+ lub <) są obliczone nawet w przypadku gdy obliczenia sa w trybie normalnym.

Czystość, a leniwe wartościowanie 21 Tryb obliczeń może mieć wpływ nie tylko na szybkość obliczeń, ale też na poprawność programów program, błędny z punktu widzenia trybu aplikacyjnego (semantyczne błędy w czasie obliczania) może być poprawny w przypadku normalnego trybu obliczeń (tutaj nie wszystko jest obliczane) Funkcja czysta wymagane jest określenie wszystkich jej argumentów Funkcja nieczysta przeciwnie Język czysty wszystkie funkcje są czyste Język nieczysty nie wszystkie funkcje są czyste Zdania języka czystego mogą być wartościowane w trybie aplikacyjnym Zdania języka nieczystego nie mogą być obliczane w trybie aplikacyjnym Scheme i ML są w tym sensie czyste Haskel nie jest językiem czystym Leniwe wartościowanie pozwala na tryb normalny obliczeń nie oblicza się wyrażeń aktualnie niepotrzebnych

Funkcje rekurencyjne 22 Przykład (SCHEME) (DEFINE (member elm lista) (COND ((NULL? lista) #f) ((EQ elm (CAR lista)) #t) (ELSE (member elm (CDR lista))) )) " Zadanie. Napisać program porównywania prostych list (bez zagnieżdżeń)

DrRacket 23 DrRacket: h_p://racket- lang.org

24 Język Haskell Wstęp

Historia, kompilatory 25 Lata 80 Główne trendy: leniwe wartościowanie funkcyjność 1987 konferencja FuncAonal Programming Languages and Computer Architecture; 1990 Haskell, poprawiony w 1998; Haskell Prime Implementacja ghc (Glasgow Haskell Compiler) ghci (Glasgow Haskell Compiler interacvve)

Charakterystyka języka 26 wysokopoziomowy funkcyjny silnie typowany; typy wnioskowane leniwy modularny; hermetyzacja w obrębie modułów kontraktowy (kontrakty są określone przez klasy typów) bez efektów ubocznych; funkcja może zwrócić efekt uboczny, który może być następnie wykorzystany ochrona stanów - monady dość trudny!

Proste początki 27 bash-3.2$ ghci GHCi, version 7.4.1: http://www.haskell.org/ ghc/ :? for help Loading package ghc-prim... linking... done. Loading package integer-gmp... linking... done. Loading package base... linking... done. Prelude> 2+3 5 Prelude> 5 5 Prelude> (+) 2 4 6

Proste początki 28 Prelude> 'x':"y" "xy" Prelude> pi 3.141592653589793 Prelude> :t pi pi :: Floating a => a Prelude> :t "co to jest?" "co to jest?" :: [Char] Prelude> sin 1.2 0.9320390859672263 Prelude> sin (1.2) 0.9320390859672263 Prelude> 2^200 1606938044258990275541962092341162602522202993782792835301376

Proste początki 29 Prelude> (sin) 2 0.9092974268256817 Prelude> let dwarazy x = 2*x Prelude> dwarazy pi 6.283185307179586 Prelude> dwarazy 2 4 Prelude> dwarazy "x <interactive>:7:1: No instance for (Num [Char]) arising from a use of `dwarazy' Possible fix: add an instance declaration for (Num [Char]) In the expression: dwarazy "x" In an equation for `it': it = dwarazy "x Prelude> :t dwarazy dwarazy :: Num a => a -> a Prelude>

Pliki programów 30 Rozszerzenie: hs (*.hs) Ładowanie: ghci hello.hs lub w ghci :load hello.hs -- PLIK hello.hs -- Taken from 'exercise-1-1.hs' module Main where c = putstrln "C!" combine before after = do before putstrln "In the middle" after main = do combine c c let b = combine (putstrln "Hello!") (putstrln "Bye!") let d = combine (b) (combine c c) putstrln "So long!"

Pliki programów 31 bash-3.2$ ghci hello.hs GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim... linking... done. Loading package integer-gmp... linking... done. Loading package base... linking... done. [1 of 1] Compiling Main ( hello.hs, interpreted ) Ok, modules loaded: Main. *Main> main C! In the middle C! So long! *Main> Leaving GHCi.

Haskell w sieci 32 h_p://www.haskell.org h_p://book.realworldhaskell.org h_p://tryhaskell.org h_p://learnyouahaskell.com

Przykład funkcji podwajania 33 Imperatywny function doubleit( n ){ // Double and store var result = (n*2); // Return result return( result ); } Haskell let double0 n = n+n double1 n = result where result = n * 2 double2 n = let result = n * 2 in result

Przykład rekurencji (7lang) 34 Plik fib.hs fib :: Integer -> Integer fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) Wydajniejsza implementacja; krotki; Plik fibkr.hs fibkr :: (Integer, Integer, Integer) -> (Integer, Integer, Integer) fibkr (x, y, 0) = (x, y, 0) fibkr (x, y, licznik) = fibkr (y, x+y, licznik - 1) fibwynik :: (Integer, Integer, Integer) -> Integer fibwynik (x, y, z) = x fib :: Integer -> Integer fib x = fibwynik (fibkr (0, 1, x))

Przykład rekurencji 35 bash-3.2$ ghci fibkr.hs GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim... linking... done. Loading package integer-gmp... linking... done. Loading package base... linking... done. [1 of 1] Compiling Main ( fibkr.hs, interpreted ) Ok, modules loaded: Main. *Main> fib 100 354224848179261915075 *Main> fib 1234 34774673918037020105251744060433596978868493492784371065735223930 41216496868459679756364593924530533774930268750207447601458424017 92378749321113719919618588095724485583919541019961884523908359133 457357334538791778480910430756107407761555218113998374287548487 *Main>

Ciąg Fibonacciego inaczej 36 1, 1, 2, 3, 5, 8, 13, 21,... + 1, 2, 3, 5, 8, 13, 21,... ----------------------------------------- = 2, 3, 5, 8, 13, 21, 34,... fibs = 1 : 1 : zipwith (+) fibs (tail fibs) Definicja fibs pozwala wyliczać elementy ciągu w czasie liniowym i dodatkowo zapamiętywać raz wyliczony element.

Kompozycja funkcji 37 Lista składa się z głowy (head) i ogona (tail) Definicja funkcji wybierającej drugi element listy: let drugi = head. tail Jest to złożenie funkcji head i tail kompozycja Wyrażenie drugi = head. tail jest równoważnikiem drugi lista = head (tail lista)

Kompozycja funkcji 38 - - Liczby Fibonacciego; krotki - - -- Pojedyncza para -- fibnastpara :: (Integer, Integer) -> (Integer, Integer) fibnastpara (x, y) = (y, x+y) -- nastepna para -- fibntapara :: Integer -> (Integer, Integer) fibntapara 1 = (1, 1) fibntapara n = fibnastpara (fibntapara (n-1)) -- pobieramy pierwszy element n-tej krotki -- fib :: Integer -> Integer fib = fst. fibntapara -- fst.fibntapara jest to odpowiednik wyrazenia fst = head (fibntapara fst) --

Przeglądanie list 39 Podział listy na głowę i ogon: *Main> let (g:o) = [1, 2, 3, 4, 5] *Main> g 1 *Main> o [2, 3, 4, 5] *Main> Dodawanie elementów (listy są homogeniczne) 1:[2, 3] [1, 2, 3] [1]:[[2, 3], [4]] [[1],[2, 3], [4]] Zakresy [1..4] [1, 2, 3, 4] [10,8..4] [10,8,6,4] take 5 [0,2..] => [0, 2, 4, 6, 8] Listy składane [x * 3 x <- [1,2,3]] [2, 3, 4] Dopasowywanie wzorca [(y, x) (x, y) <- [(1, 2), (2, 3), (3, 1)] [(2, 1), (3, 2), (1, 3)]

Funkcje wyższego rzędu 40 Funkcje anonimowe (\x -> x) Cokolwiek. Cokolwiek (\x -> x ++ to jest ) Cokolwiek to jest Funkcje map, where (plik map.hs) module Main where kwadratwszystkich lista = map kwadrat lista where kwadrat x = x * x Wykonanie: *Main> kwadratwszystkich [2, pi, 2, 3] [4.0,9.869604401089358,4.0,9.0]

Funkcje wyższego rzędu 41 Funkcje filter, foldl, foldr filter odd [1..10] [1, 3, 5, 7, 9] Składanie list w lewo i w prawo foldl (+) [1..4] 10 zwijanie i rozwijanie (currying, uncurrying) funkcji wieloargumentowych Leniwe obliczanie Zadanie. Napisać funkcję leniwego obliczania elementów ciągu Fibonacciego.

Monady 42 wejście/wyjście liczby losowe

Literatura 43 Sco_: Programming language pragmavcs Bylina + Bylina Tate: 7 języków Haskell w sieci

za tydzień...!? 44