online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
-- Exercício 3: Mônades (Maybe, Either, List) -- -- Este código define e demonstra as três Mônades solicitadas -- (Maybe, Either, List), com todas as explicações -- nos comentários, conforme a tarefa. module Main where -- Import necessário para o exemplo 'Either' (isDigit) -- para verificar se um caractere é um dígito. import Data.Char (isDigit) ---------------------------------------------------------------------- -- Caso de Uso 1: `Maybe` Monad ---------------------------------------------------------------------- -- 1. DEFINIÇÃO: -- A Mônade `Maybe` é usada para modelar computações que podem -- falhar ou retornar "nada" (um valor opcional). É a forma de -- Haskell de lidar com valores que podem ser nulos (null), -- evitando os famosos "null pointer exceptions". -- -- O tipo `Maybe a` tem dois construtores (dois possíveis valores): -- - `Just a`: Representa um sucesso, contendo um valor do tipo 'a'. -- - `Nothing`: Representa uma falha ou a ausência de um valor. -- -- Como Mônade, `Maybe` "propaga" o `Nothing` automaticamente. -- Se qualquer parte de uma cadeia de computações (em um bloco 'do') -- falhar e retornar `Nothing`, a computação inteira para -- imediatamente e retorna `Nothing`. -- 2. EXEMPLO: Divisão Segura -- Uma função de divisão normal falha (causa um erro em tempo de execução) -- se tentarmos dividir por zero. -- Uma função "segura" usando `Maybe` retorna `Nothing` nesse caso. divisaoSegura :: Double -> Double -> Maybe Double divisaoSegura _ 0 = Nothing -- Falha: Divisão por zero divisaoSegura x y = Just (x / y) -- Sucesso: Retorna o valor "embrulhado" em Just -- Agora, podemos "encadear" (chain) operações com segurança. -- Vamos calcular: (100 / 5) / 2 exemploMaybe1 :: Maybe Double exemploMaybe1 = do -- O 'do' notation para Mônades "desempacota" -- o valor de 'Just' ou para a execução em 'Nothing'. resultado1 <- divisaoSegura 100 5 -- Retorna Just 20.0, 'resultado1' se torna 20.0 resultado2 <- divisaoSegura resultado1 2 -- Retorna Just 10.0, 'resultado2' se torna 10.0 return resultado2 -- O resultado final é 'Just 10.0' -- Vamos tentar uma que falha: (100 / 0) / 2 exemploMaybe2 :: Maybe Double exemploMaybe2 = do resultado1 <- divisaoSegura 100 0 -- Retorna Nothing -- A execução "para" aqui. resultado2 <- divisaoSegura resultado1 2 -- Esta linha nunca é executada. return resultado2 -- O resultado final é 'Nothing' ---------------------------------------------------------------------- -- Caso de Uso 2: `Either` Monad ---------------------------------------------------------------------- -- 1. DEFINIÇÃO: -- A Mônade `Either` é parecida com `Maybe`, mas com uma -- melhoria: ela permite carregar um *valor* no caso de falha. -- `Maybe` só nos diz que algo falhou (Nothing), mas não o *porquê*. -- `Either` corrige isso. -- -- O tipo `Either a b` tem dois construtores: -- - `Left a`: Representa uma falha. Por convenção, 'a' é o tipo do erro -- (ex: uma String com a mensagem de erro). -- - `Right b`: Representa um sucesso (Right = Correto). 'b' é o valor -- do resultado. -- -- Como Mônade, `Either` propaga o `Left` automaticamente, -- assim como `Maybe` propaga o `Nothing`. -- 2. EXEMPLO: Parsing de String para Inteiro -- Queremos converter uma String para um Int, mas a -- String pode não ser um número válido. Em vez de `Nothing`, -- queremos retornar uma mensagem de erro. -- Tipo de alias para clareza (Erro é apenas uma String) type Erro = String parsearInteiro :: String -> Either Erro Int parsearInteiro str | null str = Left "Entrada vazia. Não é possível parsear." | not (all isDigit str) = Left ("'" ++ str ++ "' não é um número válido.") | otherwise = Right (read str) -- 'read' converte String para Int -- Agora, vamos usar isso para somar dois números (em formato string). somarStrings :: String -> String -> Either Erro Int somarStrings str1 str2 = do -- 'do' notation funciona da mesma forma num1 <- parsearInteiro str1 -- Se falhar (Left), 'somarStrings' retorna o Left num2 <- parsearInteiro str2 -- Se falhar (Left), 'somarStrings' retorna o Left return (num1 + num2) -- Se ambos 'Right', soma e retorna 'Right (soma)' -- Exemplo de sucesso exemploEither1 :: Either Erro Int exemploEither1 = somarStrings "123" "456" -- Retorna Right 579 -- Exemplo de falha exemploEither2 :: Either Erro Int exemploEither2 = somarStrings "10" "abc" -- Retorna Left "'abc' não é um número válido." ---------------------------------------------------------------------- -- Caso de Uso 3: `List` Monad ---------------------------------------------------------------------- -- 1. DEFINIÇÃO: -- A Mônade `List` (lista, `[]`) é usada para modelar -- computações "não-determinísticas". -- -- Não-determinismo é uma forma elegante de dizer que uma computação -- pode ter *múltiplos resultados possíveis* (ou zero, ou um). -- -- - `return x` (o 'pure' da Mônade) cria uma lista com um -- único elemento: `[x]`. -- - `xs >>= f` (o 'bind' monádico) é equivalente a `concatMap f xs`. -- Ele aplica a função 'f' a cada elemento de 'xs' (gerando -- várias listas) e depois "achata" (concatena) todas -- essas listas em uma só. -- 2. EXEMPLO: Gerando Combinações (Produto Cartesiano) -- Queremos todas as combinações possíveis de pares -- de duas listas. -- -- Por exemplo, dado [1, 2] e ['a', 'b'], queremos: -- (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b') -- Listas de entrada numeros :: [Int] numeros = [1, 2] letras :: [Char] letras = ['a', 'b'] -- Usando 'do' notation, a Mônade List faz o "loop" -- aninhado automaticamente para gerar todas as combinações. combinacoes :: [(Int, Char)] combinacoes = do -- 1. 'n' assume *cada valor* de 'numeros' (primeiro 1, depois 2). n <- numeros -- 2. Para *cada valor* de 'n', 'c' assume *cada valor* de 'letras'. c <- letras -- 3. 'return' (no contexto da Mônade List) "embrulha" -- o par em uma lista unitária, ex: [(1, 'a')] -- 4. O 'bind' (>>=) implícito do 'do' notation "concatena" -- todas essas listas unitárias. return (n, c) -- O código acima é "açúcar sintático" para a famosa -- "list comprehension" (compreensão de lista): -- combinacoes = [ (n, c) | n <- numeros, c <- letras ] -- -- O resultado de 'combinacoes' será: -- [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')] ---------------------------------------------------------------------- -- Função Principal (Main) para Demonstrar os Exemplos ---------------------------------------------------------------------- main :: IO () main = do putStrLn "--- 1. Testando a Mônade Maybe ---" putStrLn "Cálculo (100 / 5) / 2:" print exemploMaybe1 -- Imprime: Just 10.0 putStrLn "Cálculo (100 / 0) / 2:" print exemploMaybe2 -- Imprime: Nothing putStrLn "\n--- 2. Testando a Mônade Either ---" putStrLn "Soma de '123' e '456':" print exemploEither1 -- Imprime: Right 579 putStrLn "Soma de '10' e 'abc':" print exemploEither2 -- Imprime: Left "'abc' não é um número válido." putStrLn "\n--- 3. Testando a Mônade List ---" putStrLn "Combinações de [1, 2] e ['a', 'b']:" print combinacoes -- Imprime: [(1,'a'),(1,'b'),(2,'a'),(2,'b')]

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue