Um rápido Hello World com Haskell
Tags: haskell, beginners, functional, programming
Published: 2023-10-04 16:51:53


**TLDR**: O objetivo deste artigo é ser uma porta de entrada bem direto ao ponto, baseando-se na própria doc do Haskell, desde como configurar o ambiente de desenvolvimento até compilar e rodar seu primeiro código.

<blockquote cite="https://wiki.haskell.org/Haskell">
<p>"Haskell é uma linguagem puramente funcional avançada. Um produto open source com mais de 20 anos de pesquisa de ponta, que permite um rápido desenvolvimento de programas robustos, concisos e corretos."</p>
	<footer> <cite> Haskell Wiki </cite> </footer>
</blockquote>

#### 1. Instalando

Instale o compilador `ghc` usando o comando `curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh` no Terminal. O procedimento padrão é pressionar a tecla <kbd>enter</kbd> sempre que questionado até a instalação finalizar.

<small>PS.: Geralmente ao instalar o `ghc`, os pacotes necessários também são instalados, tornando o próximo passo desnecessário. Caso isso ocorra com sua instalação, simplesmente pule para o capítulo 2.</small>

Após a instalação, abra uma nova janela/aba do Terminal e execute o comando `ghcup tui` para começarmos a instalar os pacotes restantes.
Seguindo a própria documentação do Haskell, precisamos de 4 pacotes:
 - GHC (Glasgow Haskell Compiler, a.k.a Compilador)
 - HLS (Haskell Language Server)
 - Cabal (Ferramenta para estruturar projetos Haskell, executá-los, definir dependências, etc)
 - Stack (Alternativa para o Cabal)
Não há nenhum segredo sobre como instalar estes pacotes assim que a GUI for executada, basta navegar com as setas do teclado para escolher o pacote desejado, e instalar com `i`. Aconselho instalar os pacotes marcados como `recommended`.

#### 2. Executando seu primeiro código

Com os pacotes instalados, estamos preparados para escrever nossos primeiros códigos em Haskell. Podemos  usar `ghci` para iniciar uma CLI e rodar nosso código diretamente do terminal:

```bash
☁  ~  ghci     
GHCi, version 9.4.7: https://www.haskell.org/ghc/  :? for help
ghci> 6 + 3^2 * 4
42
```

Mas vamos usar o Vscode como IDE para escrever alguns arquivos. Vamos criar um arquivo com extensão `.hs`. Para nosso simples "Hello world" precisamos escrever o seguinte:
```haskell
main = do
putStrLn "Hello World!"
```
Podemos ver que é bem parecido com varias outras langs que conhecemos(não tô falando de você Java).

Agora vamos compilar nosso arquivo usando `ghc nome-do-arquivo.hs` , isso irá nos gerar um executável para rodar nosso programa. Aqui meu arquivo se chama simplesmente `hello-world`:
```bash
☁  ~  ghc hello-world.hs                                  
[1 of 2] Compiling Main             ( hello-world.hs, hello-world.o )
[2 of 2] Linking hello-world
```

Depois disso, basta rodar nosso executável:
```bash
☁  ~  ./hello-world
Hello World!
```

E tá feito o programinha! Vale lembrar que o arquivo foi criado e compilado na **mesma pasta**.

#### 3. Entendendo o que foi escrito

Tá mas o que é o `main = do`? É basicamente o *ponto de entrada* para a aplicação, necessário para um programa feito em Haskell. Fora de blocos iniciados com `do` as quebras de linha não fazem efeito ou diferença. Ao executar o programa, é necessário que a sequência de eventos esteja bem definida, logo usamos `do` para que dentro do seu bloco a quebra de linha seja 'respeitada' e assim definir as etapas do programa, isso deve ficar mais claro ao escrever um pouco mais de código.

Vamos adicionar mais uma linha, compilar e executar, deve rodar sem problema algum:
```haskell
main = do
putStrLn "Hello World!"
putStrLn "Bye Bye World!"
```
Compilando e executando:
```bash
☁  ~  ./hello-world
Hello World!
Bye Bye World!
```

Agora vamos forçar um erro, podemos fazer isso de duas formas diferentes, desrespeitando a quebra de linha quando usando `do`:
```haskell
main = do
putStrLn "Hello World!" putStrLn "Bye Bye World!"
```
Ou removendo o `do`
```haskell
main = 
putStrLn "Hello World!"
putStrLn "Bye Bye World!"
```

Ao tentar compilar em ambos os casos temos o seguinte erro:

```bash
 ~ ghc hello-world.hs
[1 of 2] Compiling Main             ( hello-world.hs, hello-world.o ) [Source file changed]

hello-world.hs:2:5: error:
    • Couldn't match expected type: (String -> IO ()) -> String -> t
                  with actual type: IO ()
    • The function ‘putStrLn’ is applied to three value arguments,
        but its type ‘String -> IO ()’ has only one
      In a stmt of a 'do' block:
        putStrLn "Hello, World!" putStrLn "Second line of code"
      In the expression:
        do putStrLn "Hello, World!" putStrLn "Second line of code"
    • Relevant bindings include main :: t (bound at hello-world.hs:1:1)
  |
2 |     putStrLn "Hello, World!" putStrLn "Second line of code"
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

Em resumo: nosso primeiro `putStrLn` está tentando printar a linha `"Hello, World!" putStrLn "Second line of code"`. Conseguimos corrigir isso sem o `do` adicionando `>>` no que seria o final da primeira linha:
```haskell
main = 
putStrLn "Hello World!" >>
putStrLn "Bye Bye World!"
```

Isso dará uma estrutura e ordenação para nosso código, o informando para rodar primeiro `putStrLn "Hello World!"` e depois `putStrLn "Bye Bye World!"`.

#### 4. Dever de casa

Haskell é uma linguagem funcional, logo vale escrever diferentes funções e entender seus comportamentos. 
Sugestão: Adicionar ainda mais linhas e criar suas próprias funções fora do bloco `main`.