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