W poprzednim tygodniu pisaliśmy funkcje
readInts2 :: String -> Either String [Int] sumInts :: String -> String
Przepisz funkcje readInts2, sumInts na notację monadyczną
(Uwaga: w tym zadaniu raczej nadal tworzymy funkcje String -> String i korzystamy z interact niz bezposrednio z IO, chyba ze ktos bardzo chce)
Uzupełnić przykład z wykładu:
data ParseError = Err {location::Int, reason::String}
instance Error ParseError ...
type ParseMonad = Either ParseError
parseHexDigit :: Char -> Int -> ParseMonad Integer
parseHex :: String -> ParseMonad Integer
toString :: Integer ->; ParseMonad String
-- convert zamienia napis z liczba szesnastkowa
-- na napis z liczba dziesietna
convert :: String -> String
convert s = str where
(Right str) = tryParse s `catchError` printError
tryParse s = do {n <- parseHex s; toString n}
printError e = ...Napisz własną implementację funkcji
sequence :: Monad m => [m a] -> m [a] mapM :: Monad m => (a -> m b) -> [a] -> m [b] forM :: Monad m => [a] -> (a -> m b) -> m [b]
Nieco inny od monad model obliczeń reprezentuje klasa Applicative:
class Functor f => Applicative f where pure :: a -> f a (>*>) :: f(a->b) -> f a -> f b
pure to to samo co return(<*>) reprezentuje sekwencjonowanie obliczeń podobne do (=<<)pure = return
mf <*> ma = do { f <- mf; a <- ma; return mf ma }Applicative dla Maybe i Either*> będącą analogiem >> (czyli ignorującą wynik pierwszego obliczenia):(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
Applicative zamiast Monad