module Aula30 where data Writer a = Writer (a, [String]) deriving (Eq, Show) quad_log :: Integer -> Writer Integer quad_log x = Writer (x^2, [show x ++ " ao quadrado"]) instance Functor Writer where -- fmap :: (a -> b) -> Writer a -> Writer b fmap f (Writer (x, log)) = Writer (f x, log) x = (^2) <$> Writer (2, ["dois"]) -- x = Writer (4,["dois"]) instance Applicative Writer where -- pure :: a -> Writer a pure x = Writer (x, []) -- (<*>) :: Writer (a -> b) -> Writer a -> Writer b Writer (f, log_f) <*> Writer (x, log_x) = Writer (f x, log_f ++ log_x) y = Writer ((^2), ["ao quadrado"]) <*> Writer (3, ["tres"]) -- y = Writer (9,["ao quadrado","tres"]) exemplo :: Integer -> Integer -> Integer -> Integer exemplo a b c = a * b ^ c z = Writer (exemplo, ["exemplo"]) <*> Writer (2, ["dois"]) <*> Writer (3, ["tres"]) <*> Writer (4, ["quatro"]) -- z = Writer (162,["exemplo","dois","tres","quatro"]) instance Monad Writer where -- (>>=) :: Writer a -> (a -> Writer b) -> Writer b Writer (x, log_x) >>= f = let Writer (y, log_y) = f x in Writer (y, log_x ++ log_y) -- >>= é lido "bind" ("atribuir" ou "amarrar" ou "ligar") cubo_log :: Integer -> Writer Integer cubo_log x = Writer (x^3, [show x ++ " ao cubo"]) w = quad_log 2 >>= cubo_log >>= quad_log -- w = Writer (4096,["2 ao quadrado","4 ao cubo","64 ao quadrado"]) -- notação "do" w' = do a <- quad_log 2 b <- cubo_log a c <- quad_log b return c -- w' = Writer (4096,["2 ao quadrado","4 ao cubo","64 ao quadrado"]) -- equivalente: w'' = do a <- quad_log 2 b <- cubo_log a quad_log b -- w'' = Writer (4096,["2 ao quadrado","4 ao cubo","64 ao quadrado"]) -- Monads também têm >> (lido "e então" ou "and then"), que "joga fora" o valor calculado até ali (mas não os efeitos colaterais causados) ww = quad_log 2 >>= cubo_log >> return 3 -- ww = Writer (3,["2 ao quadrado","4 ao cubo"]) -- notação do equivalente ww' = do a <- quad_log 2 cubo_log a return 3 -- ww' = Writer (3,["2 ao quadrado","4 ao cubo"]) bla = do a <- quad_log 2 Writer((), ["foobar"]) cubo_log a return 3 -- bla = Writer (3,["2 ao quadrado","foobar","4 ao cubo"])