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.

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.

Instalação de Pacotes (Hackage)

Muitas bibliotecas Haskell estão disponíveis como pacotes Cabal. Esse é um formato usado para empactoamento de bibliotecas e programas Haskell. O resultado é que tais "componentes" podem ser compilados em diferentes plataformas. A forma básica de instalar um pacote disponibilizado no formato Cabal consiste em:

  • Fazer o download do pacote. Muitos pacotes são disponibilizados no banco de dados de pacotes Haskell
  • Descompactar o arquivo que foi feito o download
  • Usar a ferramenta runhaskell para configurar, preparar o build e instalar. Abaixo um exemplo desses passos para instalar o pacote Happy

$ runhaskell Setup.lhs configure
Configuring happy-1.17...
$ runhaskell Setup.lhs build    
Preprocessing executables for happy-1.17...
Building happy-1.17...
[ 1 of 18] Compiling Set            ( src/Set.hs, dist/build/happy/happy-tmp/Set.o )
[ 2 of 18] Compiling NameSet   ( src/NameSet.hs, dist/build/happy/happy-tmp/NameSet.o )
[ 3 of 18] Compiling Target       ( src/Target.lhs, dist/build/happy/happy-tmp/Target.o )
[ 4 of 18] Compiling AbsSyn     ( src/AbsSyn.lhs, dist/build/happy/happy-tmp/AbsSyn.o )
...
[18 of 18] Compiling Main             ( src/Main.lhs, dist/build/happy/happy-tmp/Main.o )

$ runhaskell Setup.lhs install
Installing: /usr/local/bin
 

Após ter sido feita a instalação de um pacote, o mesmo se torna disponível. Isso pode ser verificado usando a ferramenta ghc-pkg (na linha de comando $ghc-pkg list). Esse comando lista as bibliotecas disponíveis no ambiente. Essa mesma ferramenta (ghc-pkg) é usada para exibir detalhes de um pacote, desabilitar pacotes, remover pacotes, etc. A ferramenta cabal instal é a segunda alternativa para instalar pacotes cabal. Com essa ferramenta,que também está disponível como um pacote cabal, é possível instalar pacotes e resolver dependências com uma única ação de linha de comando (particularmente, prefiro a alternativa apresentada anteriormente). Uma restrição é que o pacote precisa estar em um repositório acessível pela ferramenta. Em relação ao exemplo anterior, bastaria executar a linha de comando:

$ cabal install happy

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)
  • Discussão sobre Monads
  • Como processar arquivos XML em Haskell (lembrar que IO pode resultar em efeitos colaterais)
  • GUI (diferentes tecnologias, apresentar exemplos em gtk2hs e glade, ...)

-- RodrigoBonifacio - 02 May 2008

Topic revision: r2 - 2008-07-12 - RodrigoBonifacio
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2024 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