Dicas de desenvolvimento Haskell

Nessa área do Twiki são postadas alguamas dicas para o desenvolvimento Haskell, que podem ser úteis para quem está se familiarizando com essa linguagem.

Ferramentas

Compiladores e/ou interpretadores sugeridos:

  • ghc:Acredito que seja a implementação de referência das bibliotecas Haskell (isso porque alguns pacotes são validos apenas para o ghc). Um conjunto de ferramentas auxiliares é disponibilizado após a instalação (ghci, runhaskell, ghc-pkg, etc.)

  • hugs: Na versão Windows, oferece um interpretador um pouco mais amigável que o ghc interpreter. Útil para quem deseja dar os primeiros passos na linguagem. A minha conclusão é que o ghc oferece uma solução mais estável para a linguagem Haskell.

Ambiente de desenvolvimento:

  • Functional Programming Plugin: Plugin eclipse para linguagens funcionais. Apenas o suporte a linguagem Haskell foi avaliado. Razoável, principal utilidade é o editor sensível a sintaxe.

Outros tópicos a serem escritos

  • Primeiros passos em Haskell
    • (aplicações da linguagem Haskell)
    • (sugestão de livros e tutoriais)
    • (exemplos simples)
  • Definição de tipos de dados
    • (lembrar do idioma para instanciar tipos mutualmente recursivos)
    • (definição de classes básicas, como Show e Eq => novamente, cuidado com tipos recursivos)
  • Gerenciamento de pacotes
  • Discussão sobre Monads
  • Como processar arquivos XML em Haskell (lembrar que IO pode resultar em efeitos colaterais)

Entrada e Saída em Haskell

(conteúdo baseado em Yet Another Haskell Tutorial Hal Daumé III)

Não existe uma solução "elegante" para representar operações de entrada e saída como funçõe (de forma simples, tais operações apresentam efeitos colaterais). Por exemplo, qual o tipo de retorno para uma função responsável por uma operação que imprime uma String na tela? Poderíamos imaginar "()" como primeira alternativa. Por outro lado, devido à propriedade de transparência referencial, seria possível substituir tal função por qualquer outra definida como f _ = (). Obviamente, o resultado não seria o esperado.

A solução para representar operações de entrada em saída como ações (talvez Monads fosse um termo mais correto aqui) foi proposta por Phil Wadler. Ações são nomeadas e têm tipos bem definidos. Por exemplo, a ação que imprime uma String na tela é definida como:

putStrLn :: String -> IO ()

Tal ação recebe uma String como argumento e retorna o tipo IO (). Sintaticamente, esse tipo de retorno é o que diferencia uma função de uma ação. Quando a ação é avaliada, seu retorno é (). Agora considere:

getLine :: IO String

getLine é uma ação que retorna um valor String.

Um programa Haskell é uma única ação que é executada quando o programa compilado é executado. Dessa forma, os compiladores esperam que a funação main tenha tipo IO que retorna (). Não é comum executar ações diretamente. Por outro lado, as ações podem ser combinadas (utilizando a notação do) no corpo da função main. A construção do oferece os mecanismos para a composição de ações.

Por exemplo, tente executar o seguinte programa, definido em um módulo Main (ghc --make Main.hs)

main = do
 putStrLn "Por favor, entre seu nome: "
 nome <- getLine
 putStrLn ("Ola, " ++ nome ++ ", como voce vai?")

No exemplo, três ações são sequenciadas: uma impressão na tela, seguida de uma leitura da entrada padrão, seguida de outra impressão na tela. A construção "<-" é usada para expor o resultado de uma ação. Como um exemplo mais real, considere o parser de dois arquivos XML (utilizando a biblioteca HXT). O resultado do parser é atribuído aos identificadores x e y.

main :: IO ()
main = do 
   [x] <- runX ( xunpickleDocument xpUseCaseModel [ (a_validate,v_0)
               , (a_trace, v_1)
               , (a_remove_whitespace,v_1)
               , (a_preserve_comment, v_0)
               ] "completo.xml" )
   [y] <-  runX ( xunpickleDocument xpFeature [ (a_validate,v_0)
               , (a_trace, v_1)
               , (a_remove_whitespace,v_1)
               , (a_preserve_comment, v_0)
               ] "feature-model.xml" )            
   ...   

Apesar de não ter sido destacado, as operações de IO são suportadas pelo conceito de Monads. Muitas das ações de entrada e saída estão disponiveis na biblioteca IO. Algumas definições dessa biblioteca são apresentadas abaixo:

data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
openFile :: FilePath -> IOMode -> IO Handle

hClose :: Handle -> IO ()
hIsEOF :: Handle -> IO Bool
hGetChar :: Handle -> IO Char
hGetLine :: Handle -> IO String
hGetContents :: Handle -> IO String
getChar :: IO Char
getLine :: IO String
getContents :: IO String
hPutChar :: Handle -> Char -> IO ()
hPutStr :: Handle -> String -> IO ()
hPutStrLn :: Handle -> String -> IO ()
putChar :: Char -> IO ()
putStr :: String -> IO ()
putStrLn :: String -> IO ()
readFile :: FilePath -> IO String
writeFile :: FilePath -> String -> IO ()

FilePath é apenas um sinônimo para o tipo String. A ação hGetContents lê todo o conteúdo de um arquivo. Ações que começam com "h" (hGetLine, hPutStrLn) fazem acesso de leitura / escrita em arquivos. Ações similares, que não iniciam com "h" (getLine, putStrLn) fazem acesso nos dispositivos de entrada e saída padrão.

-- RodrigoBonifacio - 02 May 2008

Edit | Attach | Print version | History: r2 < r1 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r1 - 2008-05-02 - RodrigoBonifacio
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback

mersin escort bayan adana escort bayan izmit escort ankara escort bursa escort