300 likes | 436 Vues
SISEND/VÄLJUND. Kõik senised programmid on olnud ilma kõrvalefektideta Osade ülesannete jaoks on kõrvalefektid vajalikud: Suhtlus “maailmaga” Efektiivsed imperatiivsed algoritmid. Kõrvalefektidega avaldised on spetsiaalset tüüpi IO
E N D
SISEND/VÄLJUND Kõik senised programmid on olnud ilma kõrvalefektideta Osade ülesannete jaoks on kõrvalefektid vajalikud: • Suhtlus “maailmaga” • Efektiivsed imperatiivsed algoritmid
Kõrvalefektidega avaldised on spetsiaalset tüüpi IO • See on Haskelli moodus esitamaks funktsioone, mis tegelikult ei olegi funktsioonid • kõrvalefektide järjestamiseks ja täitmisekskasutatakse spetsiaalset süntaksit
Haskellis on igal avaldisel mingi tüüp ja tema väärtustamisel ontulemuseks sama tüüpi väärtus. • Käsuks (command) nimetatakse avaldist, mille väärtustamisel lisaks “puhtale väärtusele” võib tekkida kõrvalefekt. • Käsk, mille “puhas väärtus” on tüüpi a, on ise abstraktset tüüpi IO a, mille väärtusi kutsume aktsioonideks. Aktsiooni täitmisel süsteemi poolttoimub vastav kõrvalefekt. • Terviklik Haskell-programm on aktsioon tüüpi IO ().
“Tühikäsk” return :: a -> IO a • Standard-väljundisse kirjutamine putChar :: Char -> IO () putStr :: String -> IO () print :: Show a => a -> IO () Näide: Main> putStr "Hello, World!" Hello, World! Main>
Käskude kombineerimine ja järjestamine do-süntaks: expr = do {stmt; . . . ; stmt} stmt = pat m expr expr let decls Näide. main = do s <- readFile "somefile" let i = f s putStrLn (show i)
Näide. (Nimi.hs) import IO nimi = do putStrLn "Please enter your name: " name <- getLine putStrLn ("Hello, " ++ name ++ ", how are you?")
Eeldefineeritud IO operatsioonid • Standard-sisendist lugemine: getChar :: IO Char getLine :: IO String getContents :: IO String • Tekstifailide lugemine / kirjutamine: type FilePath = String readFile :: FilePath -> IO String writeFile:: FilePath -> String -> IO () appendFile:: FilePath -> String ->IO () bracket :: IO a ->(a -> IO b)->(a -> IO c)-> IO c
IO teegid module Directory createDirectory :: FilePath -> IO() removeDirectory :: FilePath -> IO() removeFile :: FilePath -> IO() renameDirectory :: FilePath -> FilePath -> IO() renameFile :: FilePath -> FilePath -> IO() getDirectoryContents:: FilePath -> IO[FilePath]
module System getArgs :: IO[String] getProgName :: IO String getEnv :: String -> IO String
Näide: getWord :: IO String getWord = do c <- getChar if isSpace c then return "" else do w <- getWord return (c:w)
Tekstifailide töötlemine • Kopeerida tekst standardsisendist standardväljundisse module Main(main) where main :: IO() main = do input <- getContents putStr input
Kopeerida tekstifailid standardväljundisse import System (getArgs) main :: IO() main = do args <- getArgs if null args then catFiles ["-"] else catFiles args
catFiles :: [String] -> IO () catFiles [] = return () catFiles ("-":xs) = do input <- getContents putStr input catFiles xs catFiles (x:xs) = do contents <- readFile x putStr contents catFiles xs
IO vigade töötlus ioError :: IOError -> IO a userError :: String -> IOError catch :: IO a ->(IOError -> IO a) -> IO a Veatöötlusega cat: catFiles (x:xs) = do cont <- catch (readFile x) (\_ -> return (msg ++ x ++ "\n")) putStr cont catFiles xs where msg = "ERROR reading file: "
Mitterekursiivne cat: catFiles :: [String] -> IO () catFiles xs = sequence_ [ catFile x | x <- xs] catFile :: String -> IO () catFile "-" = do input <- getContents putStr input catFile x = do cont <- catch (readFile x) (\_ -> return (msg ++ x ++ "\n")) putStr cont where msg = "ERROR reading file: "
Funktsiooni rakendamine $ abil f $ x = f x • Näide. Me ei saa kirjutada putStrLn "5+3=" ++ show (5+3) kuna seda tõlgendatakse kui (putStrLn "5+3=") ++ (show (5+3)), Selle asemel kirjutame: putStrLn $ "5+3=" ++ show (5+3) • Nimeta funktsioonide koostamine \… map (\x -> "the " ++ show x) [1, 2, 3, 4, 5] = ["the 1", "the 2", "the 3", "the 4", "the 5"]
Näide. Arvu äraarvamine. do … if (read guess)< num then do putStrLn “Too low doGuessing num else if read guess > num then do putStrLn “Too high!” doguessing num else putStrLn “You win!” Vale: do if (read guess) < num then putStrLn “Too Low!” doGuessing num else …
doGuessing num = do putStrLn “Enter your guess:” guess <- getLine case compare (read guess) num of LT -> do putStrLn “Too low!” doGuessing num GT -> do putStrLn “Too high!” doGuessing num EQ -> putStrLn “You win!”
Näide. Sõna äraarvamine Main> main Enter a word: ------- k ------- h h------ m h---m-- o h---m-- n h-n-m-n a han-man g hangman Enter a word:
Tüüp Interact type Interact = String -> String Funktsioon interact (eeldefineeritud prelüüdis) interact :: Interact -> IO () interact f = do input <- getContents putStr (f input) Näide: import Char(toUpper) capitalises :: Interact capitalises = map toUpper main = interact capitalises
“Hangman” (versioon 1) hangman :: Interact hangman input = "Enter a word: " ++ echo ++ "\n" ++ game word [] input’ where echo = [’-’ | _ <- word] word = before ’\n’ input input’ = after ’\n’ input before x = takeWhile (/= x) after x = tail.dropWhile (/= x) main = interact hangman
game :: String -> String -> Interact game word guess (c:input) = line ++ rest where line = [c] ++ " " ++ reveal ++ "\n" reveal = [dash w | w <- word] dash w | w ‘elem‘ (c:guess) = w | otherwise = ’-’ rest | ’-’ ‘elem‘ reveal =game word (c:guess) input | otherwise = hangman input
Interaktiivsed kombinaatorid readChar:: (Char -> Interact) -> Interact readChar prog (c:cs) = prog c cs unreadChar :: Char -> Interact -> Interact unreadChar c prog cs = prog (c:cs) writeChar :: Char -> Interact -> Interact writeChar c prog cs = c : prog cs
writeStr :: String -> Interact -> Interact writeStr s prog cs = s ++ prog cs readLine :: String -> (String -> Interact) -> Interact readLine prompt g cs = prompt ++ g line input’ where line = takeWhile (/= ’\n’) cs input’ = tail(dropWhile(/=’\n’) cs)
end :: Interact end cs = "" pressAnyKey :: Interact -> Interact pressAnyKey prog = readChar (\c -> prog) ringBell :: Interact -> Interact ringBell = writeChar ’\BEL’
“Hangman” (versioon 2) hangman = readLine "Enter a word: " $ \word -> let echo = [’-’ | _ <- word] in writeStr (echo ++ "\n") $ game word []
game word guess= readChar $ \c -> let dash w | w ‘elem‘ (c:guess) = w | otherwise = ’-’ reveal = [dash w | w <- word] in writeStr([c] ++ " " ++ reveal ++ "\n") $ if ’-’ ‘elem‘ reveal then game word (c:guess) else hangman
Ekraani kontrollimine cls :: String cls = "\ESC[2J" highlight :: String -> String highlight s = "\ESC[7m"++s++"\ESC[0m" goto :: Int -> Int -> String goto x y = "\ESC[" ++ show y ++ ";" ++ show x ++ "H" home :: String home = goto 1 1
clearScreen :: Interact -> Interact clearScreen = writeStr cls moveTo :: Pos -> Interact -> Interact moveTo (x,y) = writeStr (goto x y) writeAt :: Pos -> String -> Interact -> Interact writeAt pos s = writeStr (at pos s) readAt :: Pos -> String -> (String -> Interact) -> Interact readAt pos prompt g = moveTo pos $ readLine prompt g
“Hangman” (versioon 3) hangman = clearScreen $ readAt (1,1) "Enter a word: " $ \w -> let echo = [’-’ | _ <- w] in writeStr (echo ++ "\n") $ game w [] newgame = writeStr "Start a new game? (y/n)" $ readChar $ \c -> if toUpper(c) == ’Y’ then hangman else end