Paulo Henrique Rodrigues Pinheiro

Um blog sobre programação para programadores!


Meu "hello world" em Haskell

Para começar bem no Haskell, nada melhor que um "Hello World" firulento

Hello World em Haskell

Meu primeiro Hello World foi no clássico "C - A Linguagem de Programação", traduzido, capa rosa. Nele temos os primeiros - se não me enganei - 9 elementos da linguagem, num simples programa.

Depois de muitos anos, descobri a versão GNU do "Hello World" em C, que é praticamente um curso completo de programação C para sistemas GNU, e mais próximo à piada da imagem. Mas vai demorar um pouco para eu chegar nesse nível, ainda mais em Haskell.

Se você está lendo isso, provavelmente tem todos os requisitos necessários para se virar e instalar um compilador Haskell em sua máquina. Eu uso Fedora, então só precisei de um:


sudo dnf install haskell-platform

Com isso, tenho muito mais do que preciso, mas especialmente o compilador ghc e um interpretador REPL ghci.

Antes de sair funcionalmente programando, eu, que preciso meter a mão na massa, larguei mão de entender toda a teoria que sustenta o Haskell, e parti para a ignorância.

Chega de enrolação, eis o programa:


{- |
Module      :  $Header$
Description :  A hello world in Haskell, with steroids.
Copyright   :  (c) Paulo Henrique Rodrigues Pinheiro
License     :  MIT

Maintainer  :  [email protected]
Stability   :  experimental
Portability :  portable

A hello world program in Haskell, with various language elements.
-}

import Data.Char

-- | Puts a greeting, get a string, then puts another greeting.
main = do putStrLn "Hello World, from Haskelland."
          putStrLn "Please, type your name:"
          name <- getLine
          putStr "HI, "
          nameInUpperCase = map toUpper name
          putStr nameInUpperCase
          putStrLn "!"

Parece muita coisa, mas é por conta das firulas embutidas.

Primeiro, um longo cabeçalho, com várias informações. De acordo com as diretrizes de programação Haskell, todo arquivo fonte deve começar dessa forma. Trata-se de guideline, portanto fique tranquilo que compila sem isso.

Já foi o primeiro elemento.

Nos deparamos com um import Data.Char. Como implica o nome, import foi usado para "importar" um package. O nome dele já dá uma dica de que estamos querendo trabalhar com caracteres.

E foi o segundo elemento.

Opa! Um texto iniciado por -- |. Comentários em Haskell são feitos com --. Mas veja, esse é mais um comentário especial, para documentação do programa. É um haddock. Tem markup para várias coisas, podemos gerar documentação bem formatada a partir desses comentários. Use esse tipo de comentário para documentar cada função ou tipo de dado.

Vencemos o terceiro elemento.

Aqui embaralhou tudo. o main = do é uma declaração de função. Não apenas isso, mas um bloco.

Foi-se o quarto elemento.

Um bloco pode estar entre {} ou definido por um do, como foi feito aqui (é o recomendado). Usando o do, a indentação é requerida, como é no Python. Não use <TABS>, apenas espaços. E alinhe a próxima linha com o que vem depois do = na primeira linha.

E mandamos o quinto elemento para os quintos!

Há várias opções para imprimir, dentre as quais putStr, sem quebra de linha, e putStrLn. Chame com um argumento do tipo String.

Foi-se o sexto.

Em seguida, temos name <- getLine. A mônada IO (não queira saber tão cedo o que é uma mônada) define a função getLine que lê e retorna uma String. Direcionando a saída da função para a variável name.

Passamos enfim do sétimo.

A maravilhosa linha nameInUpperCase = map toUpper name já dá um gosto do que vem pela frente. A variável nameInUpperCase recebe o resultado da aplicação (o map faz isso) da função toUpper (definida em Data.Char) a todos os caracteres de name.

Perceba que não temos parêntesis, nem vírgulas para separar as coisas. Só espaços (os parêntesis são necessários nos casos em que possa haver confusão no entendimento do que se queira fazer, mas são usados diferentemente do convencional, por hora, deixemos isso pra lá.

O oitavo e o nono já eram!

Para compilar, salvando como hello.hs:


➤ ghc hello.hs 
[1 of 1] Compiling Main             ( hello.hs, hello.o )
Linking hello ...

E, para executar:


➤ ./hello
Hello World, from Haskelland.
Please, type your name:
paulo
HI, PAULO!

E faltou o décimo elemento, main. O Haskell precisa dessa função declarada para usar como um ponto de entrada, assim como é em C.

Nosso programa poderia ser simples dessa forma:


main = putStrLn "hello, world"

Mas se eu informasse isso no começo, não teríamos assunto.