12. Funkcionális programozás gyakorlat

Bevezetés

Írjunk egy unit típusú akciót, amely bekér egy sort és kétszer visszaírja!

Típus:

echoTwice :: IO ()

Segítség: getLine, putStrLn

Megjegyzés: Próbáljuk ki az értelmezőben. Az értelmező az akciókat előbb kiértékeli, majd végre is hajtja.

Írjunk egy unit típusú akciót, amely bekér egy sort, majd visszaírja a "You wrote" szöveggel. Ha üres sort kap, írja ki a "Blank line" szöveget.

Típus:

echo :: IO ()

Segítség: Mintaillesztés a case segítségével.

Fejlesszük tovább az előző feladatot úgy, hogy egészen addig ismételje a sorok bekérését, amíg üres sort nem adunk meg. Üres sor esetén írja ki, hogy "Good bye" és fejezze be a működést.

Típus:

echoUntilEmptyLine :: IO ()

Segítség: Alkalmazzunk rekurziót.

Ismétlés az előző gyakorlatról (1)

type Name = String
type Number = String
type Entry = (Name, Number)
type PhoneBook = [Entry]

emptyBook :: PhoneBook
emptyBook = []

Ismétlés az előző gyakorlatról (2)

findEntry :: PhoneBook -> Name -> Maybe Number
findEntry [] name = Nothing
findEntry ((e_name,e_number):es) name
  | (e_name == name) = Just e_number
  | otherwise        = findEntry es name

addEntry :: PhoneBook -> Entry -> PhoneBook
addEntry book entry = entry : book

Írjunk egy olyan akciót, amely kiírja a következő üzenetet:

Commands:
? - search
+ - new entry
s - save phonebook
l - load phonebook
n - print names
q - quit

Típus:

printHelp :: IO ()

Írjunk egy akciót, amely kiír egy szöveget soremelés nélkül, majd bekér egy sort.

Típus:

prompt :: String -> IO String

Teszteset:

*Main> prompt ">>> "
>>> hello
"hello"

A korábbi gyakorlaton szereplő findEntry segítségével írjunk egy olyan akciót, amely a prompt függvényen keresztül bekér egy nevet és egy előre megadott telefonkönyvben megkeresi a hozzátartozó számot.

Típus:

findAction'' :: PhoneBook -> IO ()

(folyt.)

(folyt.)

Tesztesetek:

*Main> findAction'' [("Teszt","1")]
name> Teszt
number: "1"

*Main> findAction'' [("Teszt","1")]
name> X
The name is not in the book.

Módosítsuk úgy az előző megoldást, hogy ha üres nevet adunk meg, akkor ne kísérelje meg a keresést.

Típus:

findAction' :: PhoneBook -> IO ()

Segítség: case, return

Módosítsuk úgy az előző megoldást, hogy folytassa a keresést egy új névvel egészen addig, amíg üres nevet nem adunk meg.

Típus:

findAction :: PhoneBook -> IO ()

Segítség: Alkalmazzunk rekurziót.

Készítsünk egy akciót (a prompt felhasználásával), amely hozzáad egy bejegyzést egy meglevő telefonkönyvhöz. Addig lehessen benne bejegyzéseket megadni, amíg nem üres nevet adunk meg.

Típus:

addAction :: PhoneBook -> IO PhoneBook

(folyt.)

(folyt.)

Teszteset:

*Main> addAction [("Teszt", "1")]
name> X
number> 2
name>
[("X","2"),("Teszt","1")]

Készítsünk egy olyan akciót, amely parancsokat vár és a következő műveleteket végzi el a paraméterként megadott telefonkönyvvel:

Típus:

eventLoop' :: PhoneBook -> IO ()

(folyt.)

(folyt.)

Teszteset:

*Main> eventLoop' emptyBook
command> +
name> X
number> 1
name>
command> ?
name> X
number: "1"
name> Y
The name is not in the book.
name>
command> q
*Main>

Egészítsük ki az előző feladatot úgy, hogy az s paranccsal el lehessen menteni egy állományba egy adott telefonkönyvet.

Típus:

saveAction :: PhoneBook -> IO ()

Segítség: prompt, writeFile, show

Megjegyzés: Az elmentett könyv kiterjesztése .book legyen!

Folytassuk az előző feladatot úgy, hogy az l paranccsal be is lehessen tölteni a telefonkönyvet. A betöltés után írjuk ki, hogy a betöltött telefonkönyvben mennyi elem található ("Loaded N entries.", ahol N a bejegyzések konkrét száma).

Típus:

loadAction :: IO PhoneBook

Segítség: prompt, readFile, read, putStrLn, return

Megjegyzés: A betöltendő könyvet mindig .book kiterjesztéssel keressük!

(nem kötelező)

Egészítsük ki az előző feladat megoldását úgy, hogy az n paranccsal ki lehessen íratni a telefonkönyv neveit.

Típus:

printNames :: PhoneBook -> IO ()

Folytassuk az evenLoop' függvényhez tartozó megoldást úgy, hogy az ismeretlen parancsokra (a printHelp függvény meghívásával) adjunk segítséget a felhasználónak.

Típus:

eventLoop :: PhoneBook -> IO ()

Az eddig megoldott feladatok összefoglalásához készítsünk egy unit típusú main akciót.

import System.IO

...

main :: IO ()
main = do
  hSetBuffering stdout NoBuffering
  putStrLn "== Phone Book Register =="
  printHelp
  eventLoop emptyBook

A main akció megírás után a program le is fordítható és önállóan futtatható:

ghc --make PhoneBook.hs