Entrada e Saida Programação Funcional Carlos Camarão Universidade Federal de Minas Gerais DCC-UFMG 2008 www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Entrada e Saı́da Operações de E/S não são funções puras Funções em Haskell são puras: aplicação de função a argumentos não tem nenhum efeito colateral — “efeito” é fornecer resultado, que pode variar apenas de acordo com argumento. Isso garante transparência referencial: qualquer ocorrência de variável v , definida como v = e, em e 0 pode ser sempre substituı́da por e, sem alterar o valor de e 0 . Exemplo: let v = e in ...v ...v ... tem o mesmo significado que: ...e ...e ... www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Ações Haskell distingue expressões de ações usando tipos: Tipos construı́dos com o construtor IO são tipos de ações Sendo t tipo, valor de tipo IO t é uma ação que, quando executada, retorna valor do tipo t Ações são “descrições de computação”: só são executadas como parte de outras ações, que começam com execução da ação principal (ou inicial) — que consiste na execução do programa — especificada por main Ações podem ser manipuladas como valores mas não podem ser executadas em funções (assim, funções não podem produzir efeito colateral) www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Funções que retornam ações em Haskell Exemplo: putChar Prelude> ’a’ ’a’ Prelude> :t putChar putChar :: Char → IO() Prelude> putChar ’a’ a 1 interpretação consiste em chamar print passando expressão submetida no prompt, se expressão não for do tipo IO a, para algum a 2 caso contrário (expressão é do tipo IO a, para algum a), interpretação consiste em executar a ação www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Combinando Ações Ações podem ser combinadas por meio da construção do: twoLett::IO () twoLett = do putChar ’O’ putChar ’i’ Ações em do são executadas seqüencialmente, na ordem especificada Regra de leiaute é importante — opcionalmente, podem ser usadas chaves e “;” do é apenas açúcar sintático (corresponde a uso de funções monádicas — como veremos adiante) para combinação de ações seqüencialmente, com estilo parecido com o de linguagens de programação imperativas www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Funções Recursivas envolvendo Ações Exemplo putStr :: String → IO() putStr (c:cs) = do putChar c putStr cs putStr [] = return () Ação return v especifica simplesmente que v pode ser obtido e passado para ação subseqüente. return:: a → IO a www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Passando Valor entre Ações echo:: IO() echo = do c ← getChar putChar c Echo> :t getChar getChar :: IO Char Echo> echo a a Echo> www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida return return não implica em “retorno da função” onde ocorre. Exemplo: twoLettx:: IO() twoLettx = do putChar ’O’ return "xxxxx" putChar ’i’ Test> twoLettx Oi Test> www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Uso de valor fornecido em return Exemplo oi:: IO() oi = do putStr "Seu nome: " nome ← getLine putStrln ("Oi, " ++ nome) Execução da ação getLine:: IO String consiste em ler uma linha do dispositivo de entrada padrão Oi> oi Seu nome: Carlos Oi, Carlos Oi> www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Funções de E/S definidas no Prelude Exemplos print:: Show a ⇒ a → IO() print = putStrLn . show getLine:: IO String getLine = do c ← getChar if c == ’\n’ then return else do cs ← getLine return (c:cs) www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida . . . Funções de E/S definidas no Prelude Exemplos putChar putStr putStrLn print getLine writeFile readFile :: Char → IO() :: String → IO() :: String → IO() :: Show a ⇒ a → IO() :: IO String :: String → String → IO() :: String → IO String www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida Estruturas de Controle sequence sequence:: [IO a] → IO [a] sequence [] = return [] sequence (a:as) = do x ← a xs ← sequence as return (x:xs) sequence recebe lista de ações que retornam valores de um dado tipo e constrói ação que consiste em i) executar seqüencialmente essas ações, na ordem em que aparecem na lista, e ii) retornar lista dos resultados de cada uma dessas ações. www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional Entrada e Saida . . . Estruturas de controle sequence sequence :: [IO a] -> IO() sequence [] = return [] sequence (c:cs) = do c sequence cs Podemos definir putStr como: putStr = sequence . map putChar www.dcc.ufmg.br/~camarao/cursos/fp Programação Funcional