Вывод строки символов на экран монитора. Ввод строки символов с клавиатуры. Создание и удаление файлов презентация

Содержание

Слайд 2

Задачи

Вывод строки символов на экран монитора
Ввод строки символов с клавиатуры
Создание и удаление файлов
Чтение

данных из файла
Запись данных в файл
Работа с командной строкой

Задачи Вывод строки символов на экран монитора Ввод строки символов с клавиатуры Создание

Слайд 3

монады

Монада ввода - вывода используется в Haskell как связующее звено между значениями, присущими

функциональному языку, и действиями, характеризующими операции ввода - вывода и императивное программирование в общем.
Порядок вычисления выражений в Haskell ограничен только зависимостями данных; реализация обладает значительной свободой в выборе этого порядка. Действия, тем не менее, должны быть упорядочены определенным образом для выполнения программы и, в частности, ввода - вывода, для того чтобы быть правильно интерпретированы.
В Haskell монада ввода - вывода предоставляет пользователю способ указать последовательное связывание действий, и реализация обязана соблюдать этот порядок.

монады Монада ввода - вывода используется в Haskell как связующее звено между значениями,

Слайд 4

монады

Термин монада происходит из отрасли математики, известной как теория категорий. Однако, с точки

зрения программиста Haskell , лучше думать о монаде как об абстрактном типе данных. В случае монады ввода - вывода абстрактными значениями являются упомянутые выше действия. Некоторые операции являются примитивными действиями, соответствующими обычным операциям ввода - вывода. Специальные операции последовательно связывают действия, соответствующие последовательным операторам (таким как точка с запятой) в императивных языках.

монады Термин монада происходит из отрасли математики, известной как теория категорий. Однако, с

Слайд 5

Все монады представлены в лице класса типов Monad - IO

class  Monad m  where     (>>=)   :: m a -> (a -> m b) -> m b     (>>)    :: m a -> m b -> m b     return  :: a -> m a     fail    :: String -> m a   

Все монады представлены в лице класса типов Monad - IO class Monad m

Слайд 6

Метод (>>=) - это оператор последовательной компоновки (sequentially composition). Иногда его ещё называют

оператором связывания (bind): он связывает два IO-действия воедино, извлекая результат, возвращённый левым действием, и передавая его в качестве аргумента правому действию
(>>=)  :: IO a -> (a -> IO b) -> IO b
Первый аргумент - это IO-действие, которое, выполнив свою работу, вернёт значение некоторого типа a. Второй аргумент - это функция, принимающая значение типа a в качестве аргумента и возвращающая IO-действие, которое, выполнив свою работу, вернёт значение некоторого типа b.

Компоновка >>=

Метод (>>=) - это оператор последовательной компоновки (sequentially composition). Иногда его ещё называют

Слайд 7

пример
main :: IO ()
main = do
text <- getLine
putStrLn $ "You said

‘ " ++ text ++ " ‘ "

main :: IO ()
main = getLine >>= \text -> putStrLn $ "You said ‘ " ++ text ++ " ‘ "

Когда “запускается” функция getLine, возвращающая IO-монаду, содержащую полученную от пользователя строку, оператор >>= вытаскивает эту строку из монады и сразу же передаёт её в качестве аргумента λ-функции, “запускающей” функцию putStrLn, которая в свою очередь вернёт другую IO-монаду.

пример main :: IO () main = do text putStrLn $ "You said

Слайд 8

Затем >>

Монадический оператор >> - это оператор “затем” (then). Это простейший случай связывания:

действия связываются без извлечения значений.

main :: IO ()
main = do
putStrLn "Denis"
putStrLn "Shevchenko"

main :: IO ()
main = putStrLn "Denis" >> putStrLn "Shevchenko"

Затем >> Монадический оператор >> - это оператор “затем” (then). Это простейший случай

Слайд 9

return

obtainTextFromUser :: IO String
obtainTextFromUser = do
putStrLn "Enter your text, please: "
firstText

<- getLine
return $ "'" ++ firstText ++ "'
Функция getLine вернёт нам монаду, из которой оператор компоновки вытащит введённую пользователем строку. Эта строка поступит на вход λ-функции, которая в свою очередь создаст новую строку на основе строки, введённой пользователем, после чего - !!! - функция return вернёт эту новоиспечённую строку обратно в IO-монаду. Вытащили значение из монады, что-то с ним сделали, а потом вернули в монаду.

return obtainTextFromUser :: IO String obtainTextFromUser = do putStrLn "Enter your text, please:

Слайд 10

Пример IO в do нотации:
main = do
putStrLn "Hello, what is

your name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!")
или, в терминах bind, использование специальной формы:
main = putStrLn "Hello, what is your name?" >>
getLine >>= \name ->
putStrLn ("Hello " ++ name ++ "!")
или, очень примитивно, без специальной формы для bind:
main = putStrLn "Hello, what is your name?" >>= \x ->
getLine >>= \name ->
putStrLn ("Hello " ++ name ++ "!")

Пример IO в do нотации: main = do putStrLn "Hello, what is your

Слайд 11

Функции вывода

 putChar  :: Char -> IO ()   putStr   :: String -> IO ()   putStrLn :: String -> IO () --добавляет символ новой строки print    :: Show a => a -> IO ()

Функция print выводит значение любого пригодного для печати типа

на стандартное устройство вывода. Пригодные для печати типы --- это те типы, которые являются экземплярами класса Show; print преобразует значения в строки для вывода, используя операцию show, и добавляет символ новой строки.
main = print ([(n, 2^n) | n <- [0..19]])

Prelude> putStr ”Hello” >> putChar ’ ’ >> putStrLn ”World!”
Hello World!

программа для печати первых 20 целых чисел и их степеней 2

Функции вывода putChar :: Char -> IO () putStr :: String -> IO

Слайд 12

Исполняемый файл

main = putStrLn "hello, world"  
Сохраняем в файле Helloword.hs и компилируем
В текущей директории
ghc --make helloworld.hs  
Появились объектный и интерфейсный файлы
Запускаем

Exe

Исполняемый файл main = putStrLn "hello, world" Сохраняем в файле Helloword.hs и компилируем

Слайд 13

Функции ввода

getChar     :: IO Char -- читаем символ   getLine     :: IO String -- читаем строку   getContents :: IO String -- Считывание всего

ввода
  interact    :: (String -> String) -> IO ()   readIO      :: Read a => String -> IO a   readLn      :: Read a => IO a

Следующая программа просто удаляет все символы, не являющиеся ASCII, из своего стандартного ввода и отображает результат на своем стандартном выводе. (Функция isAscii определена в Data.Char )
main = interact (filter isAscii)

Функции ввода getChar :: IO Char -- читаем символ getLine :: IO String

Слайд 14

getLine

main = do  
    putStrLn "Hello, what's your name?"  
    name <- getLine  
    putStrLn ("Hello" ++ name ++  ": ) ! ")  

getLine main = do putStrLn "Hello, what's your name?" name putStrLn ("Hello" ++

Слайд 15

getLine

import Data.Char  
main = do  
    putStrLn "What's your first name?"  
    firstName <- getLine  
    putStrLn "What's your last name?"  
    lastName <- getLine  
    let bigFirstName = map toUpper firstName  
        bigLastName = map toUpper lastName  
    putStrLn $ "hey " ++ bigFirstName ++ " " ++ bigLastName ++ ", how are you?"  

getLine import Data.Char main = do putStrLn "What's your first name?" firstName putStrLn

Слайд 16

программа считывает и суммирует два числа типа Integer

import System.IO
main = do
hSetBuffering

stdout NoBuffering
putStr "Введите новое целое число: "
x1 <- readNum
putStr "Введите другое целое число: "
x2 <- readNum
putStr ("Их сумма равна " ++ show (x1+x2) ++ "\n")
where readNum :: IO Integer
-- Указание сигнатуры типа позволяет избежать
-- исправления типов x1,x2 правилом по умолчанию
readNum = readLn

Summ.hs

программа считывает и суммирует два числа типа Integer import System.IO main = do

Слайд 17

getChar Программа принимает три символа с клавиатуры и выводит их в обратном порядке:

import Control.Applicative
f

:: Char -> Char -> Char -> String
f a b c = reverse $ [a,b,c]
main :: IO ()
main = print =<< f <$> getChar <*> getChar <*> getChar

Сохраним в файле ReverseIO.hs и скомпилируем:
ghc --make ReverseIO -o rev3

Дополнительным флагом -o мы попросили компилятор чтобы он сохранил исполняемый файл под именем rev3.

./ rev3

Запуск в командной строке

getChar Программа принимает три символа с клавиатуры и выводит их в обратном порядке:

Слайд 18

Файлы

  type FilePath =  String      writeFile  :: FilePath -> String -> IO ()   appendFile :: FilePath -> String -> IO ()   readFile   :: FilePath    -> IO String

Обратите внимание, что writeFile и appendFile записывают литеральную строку в файл. Для

того чтобы записать значение любого пригодного для печати типа, как в print, сначала используется функция show для преобразования значения в строку.
main = appendFile "квадраты" (show [(x,x*x) | x <- [0,0.1..2]])

-- чтение файла

-- запись строки в файл

-- добавление строки в конец файла

Файлы type FilePath = String writeFile :: FilePath -> String -> IO ()

Слайд 19

readFile

readFile
readFile :: FilePath -> IO String
import System.IO  
main = do  
    contents <- readFile “test.txt"  
    putStr contents  

readFile readFile readFile :: FilePath -> IO String import System.IO main = do contents putStr contents

Слайд 20

writeFile

writeFile :: FilePath -> String -> IO ()
import System.IO     
import Data.Char  
main = do     
    contents <- readFile “file.in"     
    writeFile “file.out" (map toUpper contents)

writeFile writeFile :: FilePath -> String -> IO () import System.IO import Data.Char

Слайд 21

Добавление данных в файл appendFile

import System.IO     
main = do     
    todoItem <- getLine  
    appendFile "todo.txt" (todoItem ++ "\n") 

Добавление данных в файл appendFile import System.IO main = do todoItem appendFile "todo.txt" (todoItem ++ "\n")

Слайд 22

openFile

import System.IO  
main = do  
    handle <- openFile  "test.txt" ReadMode  
    contents <- hGetContents handle  
    putStr contents  
    hClose handle  

import System.IO  
main = do  
    contents <- readFile «test.txt"  
    putStr contents 

openFile import System.IO main = do handle contents putStr contents hClose handle import

Слайд 23

  

data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode  
withFile :: FilePath -> IOMode -> (Handle -> IO a) -> IO a.
import System.IO     
main = do     
    withFile “test.txt" ReadMode (\handle -> do  
        contents <- hGetContents handle     
        putStr contents)  

data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode withFile :: FilePath

Слайд 24

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a  
withFile' path mode f = do  
    handle <- openFile path mode   
    result <- f handle  
    hClose handle  
    return result

main = do   
    withFile "something.txt" ReadMode (\handle -> do  
        hSetBuffering handle $ BlockBuffering (Just 2048)  
        contents <- hGetContents handle  
        putStr contents)

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a

Слайд 25

Аргументы командной строки getArgs :: IO [String]

import System.Environment   
import Data.List  
main = do  
   args <- getArgs  
   progName <- getProgName  
   putStrLn "The arguments are:"  
   mapM putStrLn args  
   putStrLn "The program name is:"  
   putStrLn progName  

$ ./arg-test first second w00t "multi word arg"  
The arguments are:  
first  
second  
w00t  
multi word arg  
The program name is:  
arg-test  

File3.hs

Аргументы командной строки getArgs :: IO [String] import System.Environment import Data.List main =

Слайд 26

Основные подходы

Основные подходы

Слайд 27

Простой ввод-вывод
import System.IO     
import Data.Char
main :: IO ()
main = do
contents <- readFile "file.in"
writeFile "file.out"

(operate contents)
operate :: String -> String
operate = ... -- ваша функция

Самая простая полезная форма ввода-вывода: прочитать файл, что-то сделать с его содержимым, а потом записать результаты в файл.

Эта программа читает file.in, выполняет функцию operate на его содержимом, а затем записывает результат в file.out. Функция main содержит все операции ввода-вывода, а функция operate — чистая.

operate :: String -> String
operate = map toUpper

Простой ввод-вывод import System.IO import Data.Char main :: IO () main = do

Слайд 28

Список действий

Если шаблон, описанный в предыдущем разделе, недостаточен для ваших задач, то следующим

шагом будет использование списка действий. Функцию main можно написать так:
main :: IO ()
main = do
x1 <- expr1
x2 <- expr2 ...
xN <- exprN
return ()

Список действий Если шаблон, описанный в предыдущем разделе, недостаточен для ваших задач, то

Слайд 29

import System.IO
import Data.Char ( toUpper )
import System.Environment
main = do
[f1,f2] <-

getArgs
h1 <- openFile f1 ReadMode
h2 <- openFile f2 WriteMode
copyFile h1 h2
hClose h1
hClose h2
copyFile h1 h2 = do
eof <- hIsEOF h1
if eof then return () else
do
c <- hGetChar h1
hPutChar h2 (toUpper c)
copyFile h1 h2

import System.IO
import Data.Char ( toUpper )
import System.Environment
main = do
[f1,f2] <- getArgs
s <- readFile f1
writeFile f2 (map toUpper s)

Копирование файлов

import System.IO import Data.Char ( toUpper ) import System.Environment main = do [f1,f2]

Слайд 30

import System.IO  
import System.Directory  
import Data.List  
main = do        
    handle <- openFile "todo.txt" ReadMode  
    (tempName, tempHandle) <- openTempFile "." "temp"  
    contents <- hGetContents handle  
    let todoTasks = lines contents     
        numberedTasks = zipWith (\n line -> show n ++ " - " ++ line) [0..] todoTasks     
    putStrLn "These are your TO-DO items:"  
    putStr $ unlines numberedTasks  
    putStrLn "Which one do you want to delete?"     
    numberString <- getLine     
    let number = read numberString     
        newTodoItems = delete (todoTasks !! number) todoTasks     
    hPutStr tempHandle $ unlines newTodoItems  
    hClose handle  
    hClose tempHandle  
    removeFile "todo.txt"  
    renameFile tempName "todo.txt" 

"todo.txt"
0 - Iron the dishes  
1 - Dust the dog  
2 - Take salad out of the oven  

Программа удаляет из файла todo.txt указанную строку

These are your TO-DO items:  
0 - Iron the dishes  
1 - Dust the dog  
2 - Take salad out of the oven  
Which one do you want to delete?  
1

deletetodo.hs

import System.IO import System.Directory import Data.List main = do handle (tempName, tempHandle) contents

Слайд 31

View , Add , Remove

import System.Environment   
import System.Directory  
import System.IO  
import Data.List  
dispatch :: [(String, [String] -> IO ())]  
dispatch =  [ ("add", add)  
            , ("view", view)  
            , ("remove", remove)  
            ]  
main = do      (command:args) <  getArgs 
    let (Just action) = lookup command dispatch      
action args 

View , Add , Remove import System.Environment import System.Directory import System.IO import Data.List

Слайд 32

View , Add , Remove

add :: [String] -> IO ()  
add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")
view :: [String] -> IO ()  
view [fileName] = do  
    contents <- readFile fileName  
    let todoTasks = lines contents  
        numberedTasks = zipWith (\n line -> show n ++ " - " ++ line) [0..] todoTasks  
    putStr $ unlines numberedTasks  

View , Add , Remove add :: [String] -> IO () add [fileName,

Слайд 33

View , Add , Remove

remove :: [String] -> IO ()  
remove [fileName, numberString] = do  
    handle <- openFile fileName ReadMode  
    (tempName, tempHandle) <- openTempFile "." "temp"  
    contents <- hGetContents handle  
    let number = read numberString  
        todoTasks = lines contents  
        newTodoItems = delete (todoTasks !! number) todoTasks  
    hPutStr tempHandle $ unlines newTodoItems  
    hClose handle  
    hClose tempHandle  
    removeFile fileName  
    renameFile tempName fileName  

View , Add , Remove remove :: [String] -> IO () remove [fileName,

Слайд 34

import System.Environment   
import System.Directory  
import System.IO  
import Data.List  
dispatch :: [(String, [String] -> IO ())]  
dispatch =  [ ("add", add)  
            , ("view", view)  
            , ("remove", remove)  
            ]  
main = do  
    (command:args) <- getArgs  
    let (Just action) = lookup command dispatch  
    action args  
add :: [String] -> IO ()  
add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")  

view :: [String] -> IO ()  
view [fileName] = do  
    contents <- readFile fileName  
    let todoTasks = lines contents  
        numberedTasks = zipWith (\n line ->  show n ++ " - " ++ line) [0..] todoTasks  
    putStr $ unlines numberedTasks  
remove :: [String] -> IO ()  
remove [fileName, numberString] = do  
    handle <- openFile fileName ReadMode  
    (tempName, tempHandle) <- openTempFile "." "temp"  
    contents <- hGetContents handle  
    let number = read numberString  
        todoTasks = lines contents  
        newTodoItems = delete (todoTasks !! number)  todoTasks  
    hPutStr tempHandle $ unlines newTodoItems  
    hClose handle  
    hClose tempHandle  
    removeFile fileName  
    renameFile tempName fileName  

Excase.hs
Todo.txt

import System.Environment import System.Directory import System.IO import Data.List dispatch :: [(String, [String] ->

Слайд 35

$ ./todo view todo.txt  
0 - Iron the dishes  
1 - Dust the dog  
2 - Take salad out of the oven  
$ ./todo add todo.txt "Pick up children from drycleaners"  
$ ./todo view todo.txt  
0 - Iron the dishes  
1 - Dust the dog  
2 - Take salad out of the oven  
3 - Pick up children from drycleaners  
$ ./todo remove todo.txt 2  
$ ./todo view todo.txt  
0 - Iron the dishes  
1 - Dust the dog  
2 - Pick up children from drycleaners  

Excase.hs
Todo.txt

$ ./todo view todo.txt 0 - Iron the dishes 1 - Dust the

Слайд 36

Монада ввода - вывода включает простую систему обработки исключений. Любая операция ввода

- вывода может вызвать исключение вместо возвращения результата.
Исключения в монаде ввода - вывода представлены значениями типа IOError. Это абстрактный тип: его конструкторы скрыты от пользователя. Библиотека IO определяет функции, которые конструируют и изучают значения IOError . Единственной функцией Prelude, которая создает значение IOError, является userError. Пользовательские значения ошибок включают строку с описанием ошибки.
userError :: String -> IOError
Исключения вызываются и отлавливаются с помощью следующих функций:
ioError :: IOError -> IO a
catch :: IO a -> (IOError -> IO a) -> IO a
Функция ioError вызывает исключение; функция catch устанавливает обработчик, который получает любое исключение, вызванное действием, защищенным catch. Исключение отлавливается самым последним обработчиком, установленным catch. Эти обработчики не действуют выборочно: они отлавливают все исключения. Распространение исключения нужно явно обеспечить в обработчике путем повторного вызова любого нежелательного исключения. Например, в
f = catch g (\e -> if IO.isEOFError e then return [] else ioError e)
функция f возвращает [], когда в g возникает исключение конца файла, иначе исключение передается следующему внешнему обработчику. Функция isEOFError является частью библиотеки IO.
Когда исключение передается за пределы главной программы, система Haskell выводит связанное с ним значение IOError и выходит из программы.
Метод fail экземпляра IO класса Monad вызывает userError так:
instance Monad IO where
...bindings for return, (>>=), (>>)
fail s = ioError (userError s)

 Обработка исключений в монаде ввода - вывода

Монада ввода - вывода включает простую систему обработки исключений. Любая операция ввода -

Слайд 37

Ошибки ввода - вывода

Ошибки типа IOError используются монадой ввода - вывода. Это

абстрактный тип; библиотека обеспечивает функции для опроса и конструирования значений в IOError:
isAlreadyExistsError --- операция завершилась неуспешно, потому что один из ее аргументов уже существует.
isDoesNotExistError --- операция завершилась неуспешно, потому что один из ее аргументов не существует.
isAlreadyInUseError --- операция завершилась неуспешно, потому что один из ее аргументов является однопользовательским ресурсом, который уже используется (например, открытие одного и того же файла дважды для записи может вызвать эту ошибку).
isFullError --- операция завершилась неуспешно, потому что устройство заполнено.
isEOFError --- операция завершилась неуспешно, потому что был достигнут конец файла.
isIllegalOperation --- операция невозможна.
isPermissionError --- операция завершилась неуспешно, потому что пользователь не имеет достаточно привилегий операционной системы на выполнение этой операции.
isUserError --- определенное программистом значение ошибки вызвано использованием fail.

Ошибки ввода - вывода Ошибки типа IOError используются монадой ввода - вывода. Это

Слайд 38

Ошибки ввода - вывода

Все эти функции возвращают значение типа Bool, которое равно True,

если ее аргументом является соответствующий вид ошибки, и False иначе.
Любая функция, которая возвращает результат IO, может завершиться с ошибкой isIllegalOperation. Дополнительные ошибки, которые могут быть вызваны реализацией, перечислены после соответствующей операции. В некоторых случаях реализация не способна различить возможные причины ошибки. В этом случае она должна вернуть isIllegalOperation.
Имеются три дополнительные функции для того, чтобы получить информацию о значении ошибки, --- это ioeGetHandle, которая возвращает Just hdl, если значение ошибки относится к дескриптору hdl, и Nothing иначе; ioeGetFileName, которая возвращает Just имя, если значение ошибки относится к файлу имя, и Nothing иначе; и ioeGetErrorString, которая возвращает строку. Для "пользовательских" ошибок (которые вызваны использованием fail), строка, возвращенная ioeGetErrorString, является аргументом, который был передан в fail; для всех остальных ошибок строка зависит от реализации.
Функция try возвращает ошибку в вычислении, явно использующем тип Either .
Функция bracket охватывает обычный способ выделения памяти, вычисления и освобождения памяти, в котором шаг освобождения должен произойти даже в случае ошибки во время вычисления. Это аналогично try-catch-finally в Java.

Ошибки ввода - вывода Все эти функции возвращают значение типа Bool, которое равно

Слайд 39

Обработка ошибок

import System.Environment
import System.IO
import System.Directory
main = do

(fileName:_) <- getArgs
fileExists <- doesFileExist fileName
if fileExists
then do contents <- readFile fileName
putStrLn $ "The file has " ++ show (length (lines contents)) ++ " lines!"
else do putStrLn "The file doesn't exist!"

doesFileExist

doesFileExist :: FilePath -> IO Bool

Error.hs

Обработка ошибок import System.Environment import System.IO import System.Directory main = do (fileName:_) fileExists

Слайд 40

import System.Random
import Control.Monad(when)
main = do
gen <- getStdGen


askForNumber gen
askForNumber :: StdGen -> IO ()
askForNumber gen = do
let (randNumber, newGen) = randomR (1,10) gen :: (Int, StdGen)
putStr "Which number in the range from 1 to 10 am I thinking of? "
numberString <- getLine
when (not $ null numberString) $ do
let number = read numberString
if randNumber == number
then putStrLn "You are correct!"
else putStrLn $ "Sorry, it was " ++ show randNumber
askForNumber newGen

Генерация случайных чисел

Rnd.hs

import System.Random import Control.Monad(when) main = do gen askForNumber gen askForNumber :: StdGen

Имя файла: Вывод-строки-символов-на-экран-монитора.-Ввод-строки-символов-с-клавиатуры.-Создание-и-удаление-файлов.pptx
Количество просмотров: 56
Количество скачиваний: 0