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

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

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

Haskell Input and Output Źródło:

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

1 Podstawy c++ w pigułce.

Część 4 życie programu

Programowanie w języku Python. Grażyna Koba

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Haskell Moduły Ładowanie

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

lekcja 8a Gry komputerowe MasterMind

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

Bash - wprowadzenie. Bash - wprowadzenie 1/39

4. Wyrzuć wyjątek jeśli zmienna ist nie istnieje bloki: try, catch i wyrzucanie wyjątku

1 Podstawy c++ w pigułce.

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

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

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda.

Ćwiczenie: JavaScript Cookies (3x45 minut)

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

Podstawy i języki programowania

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

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Programowanie obiektowe

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

#include <stdio.h> int main( ) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

Pliki wykład 2. Dorota Pylak

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

Programowanie w językach wysokiego poziomu

Podstawy Pythona. Krzysztof Gdawiec. Instytut Informatyki Uniwersytet Śląski

Programowanie w języku C++ Grażyna Koba

#include <stdio.h> void main(void) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

1 Powtórzenie wiadomości

Zakład Systemów Rozproszonych

Zadanie nr 3: Sprawdzanie testu z arytmetyki

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Zmienne powłoki. Wywołanie wartości następuje poprzez umieszczenie przed nazwą zmiennej znaku dolara ($ZMIENNA), np. ZMIENNA=wartosc.

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.

Zasady programowania Dokumentacja

Pliki. Informacje ogólne. Obsługa plików w języku C

1 Pierwsze kroki w C++ cz.3 2 Obsługa plików

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

Lekcja 10. Uprawnienia. Dołączanie plików przy pomocy funkcji include() Sprawdzanie, czy plik istnieje przy pmocy funkcji file_exists()

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

System operacyjny Linux

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Algorytm. a programowanie -

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

Język C : programowanie dla początkujących : przewodnik dla adeptów programowania / Greg Perry, Dean Miller. Gliwice, cop

Podstawy JavaScript ćwiczenia

Wstęp do informatyki- wykład 7

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

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

Formy dialogowe w środowisku Gnome

Skrypty i funkcje Zapisywane są w m-plikach Wywoływane są przez nazwę m-pliku, w którym są zapisane (bez rozszerzenia) M-pliki mogą zawierać

Wprowadzenie do języka Java

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Instrukcje wyboru. Tworzenie programu, Schematy blokowe, Instrukcje wyboru, Operatory logiczne

5.2. Pierwsze kroki z bazami danych

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?

Wykład PASCAL - Pliki tekstowe

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

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

Inicjacja tablicy jednowymiarowej

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

Skrypty powłoki Skrypty Najcz ciej u ywane polecenia w skryptach:

JAVAScript w dokumentach HTML (1) JavaScript jest to interpretowany, zorientowany obiektowo, skryptowy język programowania.

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Projekty zaliczeniowe Podstawy Programowania 2012/2013

Strumienie, pliki. Sortowanie. Wyjątki.

Programowanie w Logice

Programowanie I. O czym będziemy mówili. Plan wykładu nieco dokładniej. Plan wykładu z lotu ptaka. Podstawy programowania w językach. Uwaga!

Wstęp do Informatyki i Programowania Laboratorium: Lista 0 Środowisko programowania

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

Instrukcje wyboru. Tworzenie programu, Schematy blokowe, Instrukcje wyboru, Operatory logiczne

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

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

Konstrukcje warunkowe Pętle

INFORMATYKA Studia Niestacjonarne Elektrotechnika

UMOWY INSTRUKCJA STANOWISKOWA

Programowanie w języku Haskell

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Język C++ wykład VIII

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

3. Opracować program kodowania/dekodowania pliku tekstowego. Algorytm kodowania:

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

Python jest interpreterem poleceń. Mamy dwie możliwości wydawania owych poleceń:

Podstawy programowania Laboratorium. Ćwiczenie 2 Programowanie strukturalne podstawowe rodzaje instrukcji

Cw.12 JAVAScript w dokumentach HTML

Metody Metody, parametry, zwracanie wartości

Programowanie w Turbo Pascal

Programowanie komputerowe. Zajęcia 1

Naukę zaczynamy od poznania interpretera. Interpreter uruchamiamy z konsoli poleceniem

4. Pliki Informacje ogólne o dostępie do plików w PHP Sprawdzanie istnienia pliku file_exists()

Pliki wykład 2. Dorota Pylak

Podstawy Programowania C++

Wstęp do programowania

Transkrypt:

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ć zawsze tą samą wartość niezależnie od tego ile razy i w jakim kontekście zostanie wywołana. Gdyby funkcje wejścia/wyjścia zwracały wartość np. odczytaną z klawiatury to zaprzeczały by idei Haskella, gdyż dla dwóch różnych wywołań z tymi samymi wartościami parametrów otrzymywalibyśmy różne wyniki. Więc w jaki sposób nasze programy mają komunikować się ze światem zewnętrznym? Haskell rodzi sobie z tym problemem definiując typ wejściowo - wyjściowy, którego wartości zwracają funkcję wejścia wyjścia np. funkcja getline odczytuje linię ze standardowego wejścia: ghci> :t getline getline :: IO String

Ze względu na fakt zmiany stanu jako efekt uboczny działania funkcji w Hasklellu funkcje dzielimy na czyste i nieczyste: Funkcje czyste: Zawsze zwracają ten sam wynik przy tych samych argumentach. Nigdy nie posiadają efektów ubocznych. Nie zmieniają stanów. Funkcje nieczyste: Mogą zwracać różne wyniki przy tych samych argumentach. Mogą posiadać efekty uboczne. Mogą zmieniać globalny stan programu lub systemu.

Rodzina typów IO, zawiera zestaw funkcji takich jak: putchar, putstr, putstrln, print, getchar, getline. Sygnatury: putchar :: Char -> IO () putstr :: String -> IO () putstrln :: String -> IO () print :: Show a => a -> IO () getchar :: IO Char getline :: IO String Zauważmy, że funkcje wyjściowe zwracają wynik typu IO (), gdzie () oznacza typ pusty, zaś funkcje wejściowe zwracają wynik typu IO a, gdzie a jest typem wczytywanej wartości.

Pierwszy program Hello world!!! Na początek przygotujmy klasyczny program Witaj świecie. W edytorze tekstowym piszemy: main = putstrln Witaj świecie!" Uruchamiamy naszą funkcję i wyświetla nam się nasz tekst.

Wydaje się ograniczające aby cały program był tylko jedną akcją I/O. Dlatego też możemy użyć składni do do sklejenia razem pewnej liczby akcji I/O w jedną: putstrln "Podaj imię:" imię <- getline putstrln ("Witaj " ++ imię ++ ".") Wartości zwracane przez funkcje nieczyste (w tym funkcje wejścia wyjścia odczytujemy przez wiązanie wartości: imię <- getline Należy przez to rozumieć: wykonaj akcję wejścia/wyjścia getline i zwiąż jej wynik z imię.

Przypisanie: imię = getline spowodowałoby nadanie funkcji getline nowej nazwy! Wiązanie jest odpowiednikiem let dla funkcji czystych. Taki kod przypomina nieco programowanie imperatywne. Użycie do pozwala na związanie wielu kroków wejścia wyjścia w jedną operację. Użycie do tworzy akcję wejścia wyjścia, której typ jest taki sam jak typ ostatniej operacji. W związku z tym funkcja main ma sygnaturę main :: IO <coś>, gdzie <coś> jest konkretnym typem.

Funkcje IO putstr pobiera string jako parametr i zwraca akcję wejścia/wyjścia, która pisze do terminala (nie przechodzi do nowej linii). putstrln przechodzi do nowej linii po przeczytaniu słowa. putstr "Witam," putstr " co " putstrln "słychać!"

Funkcje IO putchar pobiera znak jako parametr i zwraca akcję wejścia/wyjścia, która pisze ten znak do terminala. putchar 'W' putchar 'M' putchar 'i' putchar 'I'

Funkcje IO print bierze wartość która jest instancją show (co znaczy że wiemy jak ją reprezentować w formie tekstowej), wywołuje show. W zasadzie jest to putstrln. show. i Najpierw jest uruchomiony show z daną wartością, a później putstrln, co zwraca I/O akcje która wyświetli wartość. print True print 3 print xd" print [1,2,3]

Funkcje IO getchar czyta znak ze standardowego wejścia. c <- getchar if c /= ' ' then do putchar c main else return ()

Operatory klasy Monad Operator >>= służy do przekazywania wartości typu IO getchar >>= putchar Operator >>= przekazuje wynik pierwszej operacji jako argument dla drugiej. Jeśli wynik ten nie jest interesujący (np. jest pusty) używa się operatora >>. Można zatem powiedzieć, że operatory >>= i >> spełniają podobną rolę jak średnik w językach imperatywnych. Funkcję when można odnaleźć w Control.Monad. Jest ona interesująca z tego względu, że w bloku do wygląda jak wyrażenie sterujące przepływem. Przyjmuje ona wartość logiczną i w przypadku fałszu zwraca return () zaś dla prawdy akcję wejścia/wyjścia. import Control.Monad c <- getchar when (c /= ) $ do putchar c main

sequence pobiera listę akcji wejścia/wyjścia i zwraca te akcje wykonywane jedna po drugiej. a <- getline b <- getline c <- getline print [a, b, c] Można zapisać jako: rs <- sequence [getline, getline, getline] print rs Widać że sequence [getline, getline, getline] tworzy akcję I/O która wykona trzy razy getline. Jeśli powiążemy tę akcję z jakąś nazwą, wynikiem będzie lista wszystkich rezultatów, a w powyższym przykładzie lista trzech rzeczy które użytkownik wpisał z klawiatury.

forever pobiera akcję wejścia/wyjścia i zwraca tę akcję powtarzając ją. main = forever $ do putstr Wpisz coś: " l <- getline putstrln $ map toupper l

Pisanie z i do plików Do tej pory poznaliśmy funkcję getchar, która czytała pojedynczy znak, getline, która zaczytywała całą linię. Ale istnieje jeszcze funkcja o nazwie getcontens która czyta wszystkie znaki dopóki nie zostanie osiągnięty koniec pliku. contents <- getcontents putstr (map toupper contents) Uchwyty do plików: Istnieją również funkcje odpowiadające dotychczas poznanym, lecz operujące na uchwytach do plików: hgetcontents, działa jak getcontents, ale dla konkretnego pliku, istnieje również hgetline, hputstr, hputstrln, hgetchar, itp. Działają po prostu jak ich odpowiedniki bez h, tylko przyjmują uchwyt jako parametr i działają na tym konkretnym pliku zamiast działać na standardowym wejściu lub standardowym wyjściu. Przykład: putstrln to funkcja, która pobiera ciąg znaków i zwraca operacje I/O, która wydrukuje ten ciąg na terminal i znak nowej linii po tym. hputstrln bierze uchwyt i ciąg znaków i zwraca działanie I/O, które zapisze ten ciąg do pliku powiązanego z uchwytem, a następnie umieści znak nowej linii po tym. hgetline bierze uchwyt i zwraca I/O akcje odczytującą linię z pliku.

Funkcja readfile ma sygnaturę typu: readfile :: FilePath -> IO String. Funkcja readfile bierze ścieżkę dostępu razem z nazwą pliku jako pierwszy parametr i zwraca akcję I/O która wczyta zawartość pliku i powiąże zawartość do jakiegoś string-u. Użycie owej funkcji jest poręczniejsze niż używanie openfile, powiązywanie uchwytu pliku do nazwy, po czym wywoływanie hgetcontents. Przygotujmy plik zadanie.txt: Linia pierwsza Druga Trzecia Czwarta import System.IO uchwyt <- openfile zadanie.txt" ReadMode zawartosc <- hgetcontents uchwyt putstr zawartosc hclose uchwyt Zauważmy, że sami musimy zamknąć uchwyt do pliku. contents <- readfile "zadanie.txt" putstr contents

Funkcja writefile ma typ:writefile :: FilePath -> String -> IO (). Bierze ścieżkę dostępu wraz z nazwą pliku jako pierwszy parametr, String do zapisania do pliku jako drugi parametr i zwraca akcję I/O która wykona zapis do pliku. Jeśli plik już istnieje, zostanie skrócony do długości 0, przed zapisaniem danych. Oto jak zmienić plik zadanie.txt w wersje zapisaną dużymi literami i zapisanie go jako zadaniecaps.txt: import System.IO import Data.Char contents <- readfile "zadanie.txt" writefile "zadaniecaps.txt" (map toupper contents) Sygnatury: openfile :: FilePath -> IOMode -> IO Handle readfile :: FilePath -> IO String writefile :: FilePath -> String -> IO () appendfile :: FilePath -> String -> IO () withfile :: FilePath -> IOMode -> (Handle -> IO a) -> IO a

Funkcja appendfile ma sygnaturę typu taką samą jak writefile. appendfile nie skraca pliku do długości zero przed zapisaniem jeśli plik już istnieje, ale dodaje nowe rzeczy na końcu pliku. Zróbmy program który wczytuje linie ze standardowego wejścia i dodaje do pliku zadanie.txt. import System.IO handle <- getline appendfile "zadanie.txt" (handle ++ "\n") Sygnatury: openfile :: FilePath -> IOMode -> IO Handle readfile :: FilePath -> IO String writefile :: FilePath -> String -> IO () appendfile :: FilePath -> String -> IO () withfile :: FilePath -> IOMode -> (Handle -> IO a) -> IO a

Możliwe wartości trybu wejścia/wyjścia: Tryb IO Czytanie Pisanie Pozycja startowa w pliku Uwagi ReadMode TAK NIE początek Plik musi istnieć WriteMode NIE TAK początek Jeżeli plik istnieje jest czyszczony ReadWriteMode TAK TAK początek jeżeli plik nie istnieje jest tworzony; w przeciwnym wypadku dane pozostają nienaruszone AppendMode NIE TAK koniec jeżeli plik nie istnieje jest tworzony; w przeciwnym wypadku dane pozostają nienaruszone

Przekazywanie argumentów w linii poleceń Służą do tego funkcje: oraz getargs (getargs :: IO [String]) getprogname (getprogname :: IO String) Pierwsza z tych akcji wejścia/wyjścia pobiera argumenty, z którymi został uruchomiony program i przechowuje je w postaci listy zaś druga zwraca nazwę wykonywanego programu. import System.Environment import Data.List argumenty <- getargs nazwa <- getprogname putstrln "Podano argumenty:" mapm putstrln getargs putstrln "Nazwa programu to:" putstrln nazwa

Losowe dane W każdym języku programowania bywa przydatna możliwość generowania losowych danych. Taką opcję dostarcza nam również haskell dzięki pakietowi System.Random. random (generator) :: (Typ, StdGen) zwraca losową wartość typu Typ oraz nowy generator losowy. mkdstdgen (liczba) tworzy generator o podanej wartości seed/ziarna. randoms (generator) :: [Typ] zwraca nieskończoną listę typu Typ. randomr (min, max) (generator) jak random, tylko w przedziale min-max randomrs (min, max) (generator) :: [Typ] połączenie randoms i randomr Przykład: losuj = do gen <- newstdgen putstrln $ take 4 (randomrs ('1','6') gen)