module Aula27 where import Aula25 import Control.Applicative (liftA3) import Control.Monad import Aula13 (Talvez (..)) import Aula26 () -- importa as declarações de instance! data AcumulaErros a = Erros [String] | Correto a deriving (Eq, Show) instance Functor AcumulaErros where fmap :: (a -> b) -> AcumulaErros a -> AcumulaErros b fmap fun (Erros e) = Erros e fmap fun (Correto val) = Correto $ fun val instance Applicative AcumulaErros where pure :: a -> AcumulaErros a pure = Correto (<*>) :: AcumulaErros (a -> b) -> AcumulaErros a -> AcumulaErros b (Erros erros_fun) <*> (Erros erros_val) = Erros (erros_fun ++ erros_val) (Erros erros_fun) <*> _ = Erros erros_fun _ <*> (Erros erros_val) = Erros erros_val (Correto fun) <*> (Correto val) = Correto $ fun val converte :: OuErro a -> AcumulaErros a converte (OK val) = Correto val converte (Erro e) = Erros [e] validaNome'' :: String -> AcumulaErros String validaNome'' = converte . validaNome' validaIdade'' :: Integer -> AcumulaErros Integer validaIdade'' = converte . validaIdade' validaArrobas'' :: Integer -> AcumulaErros Integer validaArrobas'' = converte . validaArrobas' cvf'' :: String -> Integer -> Integer -> AcumulaErros Vaca cvf'' nome idade arrobas = (liftA3 MkVaca) (validaNome'' nome) (validaIdade'' idade) (validaArrobas'' arrobas) newtype Log a = MkLog ([String],a) deriving (Eq, Show) instance Functor Log where fmap :: (a -> b) -> Log a -> Log b fmap f (MkLog (l, val)) = -- MkLog (l ++ ["fiz um fmap"], f val) MkLog (l, f val) instance Applicative Log where pure :: a -> Log a pure val = MkLog ([], val) (<*>) :: Log (a -> b) -> Log a -> Log b (MkLog (log_fun, fun)) <*> (MkLog (log_val, val)) = MkLog (log_val ++ log_fun, fun val) soma_e_loga :: Integer -> Log (Integer -> Integer) soma_e_loga n = MkLog (["somei " ++ show n], (n+)) quasePure :: Show a => a -> Log a quasePure val = MkLog (["Comecei com " ++ show val], val) x :: Log Integer x = quasePure 10 y = (soma_e_loga 15) <*> x z = (soma_e_loga 77) <*> y ---------- -- Monads! ---------- -- Listas são Monad! -- return val = [val] -- join :: [[a]] -> [a] -- join = concat -- Talvez é Monad! instance Monad Talvez where -- enc_x >>= g = join (g <$> enc_x) where -- join :: Talvez (Talvez a) -> Talvez a -- join Nada = Nada -- join (DeFato Nada) = Nada -- join (DeFato (DeFato val)) = DeFato val (>>=) :: Talvez a -> (a -> Talvez b) -> Talvez b Nada >>= _ = Nada (DeFato val) >>= g = g val -- IO é Monad! -- getLine :: IO String -- putStrLn :: String -> IO () res = getLine >>= putStrLn