Funkcionális programozás 11. előadás Sapientia Egyetem, Műszaki és Humántudományok Tanszék Marosvásárhely, Románia mgyongyi@ms.sapientia.ro 2016, tavaszi félév
Miről volt szó? Haskell I/O műveletek, feladatok: születési dátum, névnap keresés Kombinatorikai feladatok
Miről lesz szó? Haskell hibakezelés az error függvény az catch függvény a Maybe érték az Either érték feladatok: racionális számok sorozata
Hibakezelés, az error függvény Kisebb, informális programkódok esetében használják: mydiv :: Double -> Double -> Double mydiv _ 0 = error "Zeroval valo osztas" mydiv n m = n / m > mydiv 2 3 0.6666666666666666 > mydiv 3 0 *** Exception: Zeroval valo osztas
Hibakezelés, a catch függvény A függvény szignatúrája: catch :: Exception e => IO a -> (e -> IO a) -> IO a Két paramétere van: az a típusú ellenőrző függvény és egy kivételkezelő függvény, a visszatérítési érték típusa is a lesz. import Control.Exception fel :: Double -> Double -> IO() fel x y = catch (print $ mydiv x y) handler where handler :: SomeException -> IO () handler err = putstrln $ "Caught exception: " ++ show err > fel 2 3 0.6666666666666666 > fel 2 0 Caught exception: Zeroval valo osztas
Hibakezelés, a Maybe érték részlegesen értelmezett függvények (partial functions): nincsenek definiálva az argumentumértékek minden esetében, ilyenkor egy Maybe érték lehet a visszatérítési érték data Maybe a = Nothing Just a minden a típusra használható mintaillesztéssel lehet eldönteni, hogy mi a függvény visszatérítési értéke a Maybe érték segítségével az dönthető el csupán, hogy hiba adódott
Hibakezelés, a Maybe érték mydiv1 :: Double -> Double -> Maybe Double mydiv1 _ 0 = Nothing mydiv1 n m = Just (n / m) > mydiv1 2 3 Just 0.6666666666666666 > mydiv1 3 0 Nothing
Hibakezelés, a Maybe érték fel1 :: Double -> Double -> IO() fel1 x y = case mydiv1 x y of Nothing -> putstrln "Zeroval valo osztas" Just k -> putstrln (show k) > fel1 2 3 0.6666666666666666 > fel1 3 0 Zeroval valo osztas
Hibakezelés, a Maybe érték divsum1 :: Double -> Double -> Double -> Maybe Double divsum1 x y z = do temp1 <- mydiv1 x y temp2 <- mydiv1 x z return (temp1 + temp2) > divsum1 3 4 0 Nothing > divsum1 3 0 2 Nothing > divsum1 2 3 3 Just 1.33333333333333
Hibakezelés, a Maybe érték myhead1 :: [a] -> Maybe a myhead1 [] = Nothing myhead1 ve = Just (head ve) > myhead1 "Sapientia" Just S > myhead1 "" Nothing
Hibakezelés, az Either érték hasonlóan a Maybe-hez a Prelude-ben van definiálva és két paramétere van: data Either a b = Left a Right b A Left esete a hibát jelzi, és hibaüzenetre is van lehetőség a Right esetében sikeres a kód végrehajtása a Maybe érték segítségével az dönthető el csupán, hogy hiba adódott
Hibakezelés, a Either érték mydiv2 :: Double -> Double -> Either String Double mydiv2 _ 0 = Left ("Zeroval valo osztas ") mydiv2 n m = Right (m/n) > mydiv2 2 3 Right 0.6666666666666666 > mydiv2 3 0 Left "Zeroval valo osztas "
Hibakezelés, a Either érték fel2 :: Double -> Double -> IO() fel2 x y = case mydiv2 x y of Left str -> putstrln str Right k -> putstrln (show k) > fel2 2 3 0.6666666666666666 > fel2 3 0 Zeroval valo osztas
Hibakezelés, a Either érték myhead2 :: [a] -> Either String a myhead2 [] = Left ("ures lista") myhead2 ve = Right (head ve) > myhead2 "Sapientia" Right S > myhead2 "" Left "ures lista"
Hibakezelés, a Monad és a fail használata az előbbi megoldások általánosítása: mydiv3 :: (Monad a) => Double -> Double -> a Double mydiv3 n 0 = fail "Zeroval valo osztas" mydiv3 n m = return (n / m) fel3_1 :: Double -> Double -> IO () fel3_1 x y = case mydiv3 x y of Nothing -> putstrln "Zeroval valo osztas" Just k -> putstrln (show k) fel3_2 :: Double -> Double -> IO () fel3_2 x y = case mydiv3 x y of Left str -> putstrln str Right k -> putstrln (show k)
Hibakezelés, a Monad, a fail és a catch import Control.Exception fel3_3 :: Double -> Double -> IO() fel3_3 x y = catch ( do k <- mydiv3 x y putstrln (show k) ) handler where handler :: SomeException -> IO () handler err = putstrln $ "Caught exception: " ++ show err > fel3_3 2 3 0.6666666666666666 > fel3_3 2 0 Caught exception: user error (Zeroval valo osztas)
Hibakezelés, IO hibák import System.IO.Error mygetchar :: IO Char mygetchar = catchioerror (getchar) handler where handler err = do putstrln $ "Caught exception: " ++ show err return \ n mygetchar1 :: IO Char mygetchar1 = catchioerror getchar (\ err -> return \ n )
Hibakezelés, ioerror és catch mydiv4 :: Double -> Double -> IO Double mydiv4 x 0 = ioerror (usererror "Zeroval valo osztas") mydiv4 x y = return (x / y) fel4 :: Double -> Double -> IO () fel4 x y = catch (do k <- mydiv4 x y putstrln (show k) ) handler where handler :: SomeException -> IO () handler err = putstrln $ "Caught exception: " ++ show err
Feladatok 1. feladat Generáljuk ki a pozitív racionális számok sorozatát egy megadott értékig, a következők alapján, ahol szűrjük ki az ismétlődő elemeket: [1/1, 1/2, 2/1, 1/3, 2/2, 3/1, 1/4, 2/3, 3/2, 4/1,...] lnko :: Integer -> Integer -> Integer lnko a b b == 0 = a otherwise = lnko b (a mod b) elista :: Integer-> [(Integer, Integer)] elista n = map fugv (lista n) where lista n = zip [1..n] [n, n-1..1] fugv (x, y) = (x1, y1) where x1 = x div l y1 = y div l l = lnko x y
Feladatok 1. feladat ratlistai :: Integer -> [(Integer, Integer)] ratlistai i = (elista i) ++ ( ratlistai (i+1) ) halmaz :: [(Integer, Integer)] -> [(Integer, Integer)] halmaz [] = [] halmaz (k: ve) = k: halmaz [x x <- ve, x /= k] mainf1 :: (Integer, Integer) -> [(Integer, Integer)] mainf1 (nr1, nr2) = halmaz (takewhile (/= (tnr1, tnr2)) (ratlistai 1)) where tnr1 = nr1 div l tnr2 = nr2 div l l = lnko nr1 nr2
Feladatok 2. feladat Generáljuk ki a pozitív racionális számok sorozatát egy megadott értékig, a következők alapján: az x után következő racionális szám: 2 x + 1 x y y y reciproka, ahol alsó egész részt jelöl. Példák: 5 5 2 2 + 1 5 2 2 = 2 2 + 1 5 2 = 5 5 (10 5) = = 5 2 2 2 2 5 5 5 3 2 + 1 5 3 3 = 2 1 + 1 5 3 = 3 5 (9 5) = = 4 3 3 3 3 4
Feladatok 2. feladat nextrat :: (Integer, Integer) -> (Integer, Integer) nextrat (x, y) = (y div l, x1 div l) where x1 = (2 * floor ((fromintegral x)/(fromintegral y)) + 1) * y l = lnko x1 y - x ratlistaii :: (Integer, Integer) -> [(Integer, Integer)] ratlistaii (x, y) = (x, y) : ratlistaii (nextrat (x, y))
Feladatok 2. feladat mainf2 :: (Integer, Integer) -> [(Integer, Integer)] mainf2 (nr1, nr2) = takewhile (/= (tnr1, tnr2)) (ratlistaii (1,1)) where tnr1 = nr1 div l tnr2 = nr2 div l l = lnko nr1 nr2
Feladatok 3. feladat Adott n szám, határozzuk meg, hogy hányféleképpen álĺıtható elő egy adott xs összeg, az n számból, ha mindegyik számot csak egyszer használhatom fel, az eredményt írjuk ki állományba. Megoldási ötlet: előálĺıtjuk az 1, 2, stb elemű részhalmazokat(listákat) majd kiválasztjuk azokat a listákat melyeknek elemeinek összeg xs.