Perfeccionista? Eu?
November 29th, 2006
Não. Sou um sujeito normal, que muitas vezes escreve errado, fala errado e tem preguiça. Não quer dizer que eu faça por gosto. Procuro não escrever ou falar tão errado e, se alguma coisa está ao alcance da mão, não vejo o maior problema em estender o braço.
Bem, o TaQ estava falando com o Ronaldo Ferraz em um evento sobre Ruby On Rails que falou sobre Haskell . Parece que a instalação do TaQ foi relativamente simples (para quem conhece o SO que usa e tem um pouquinho de sorte). Como troquei de SO, tirei o bom e simples PCLinuxOS (um Linux mais fácil que Windows) e instalei o bom e nem tão simples Arch , as coisas foram bem simples. Bastou um sudo pacman -S hgc O nem tão simples se refere a instalação (é divertido mas meio sacal ficar usando o nano para editar os arquivos de configuração durante a instalação toda no modo texto). Também já tive dois problemas após a atualização de programas. Uma foi resolvida com a criação de um link simbólico e, a outra foi necessário tirar o gdm (troquei pelo kdm). Acho que ambas fariam um novato voltar para o Windows. Mas aqui está tudo funcionando normalmente.

Mas vamos ao que interessa. Recentemente o MarkCC colocou uma pergunta no seu blog questionando o interesse de uma sére de artigos sobre Haskell. Como as respostas foram favoráveis, ele iniciou.
Eu ia enviar um email para o TaQ informando do tutorial quando vejo a entrada que ele colocou no dia 28. Como sempre a velha definição incompleta do fatorial.
fact n = if n == 0 then 1 else n * fact (n - 1)
Aparentemente, tudo bem. Nada demais. Só que eu leio por aí coisas como “Haskell permite escrever programas em menos tempos e corretos na primeira tentativa”. Linguagens que implementam estrutura para dificultar a ocorrência de erros no processamento como “Design by Contract”. Métodos para facilitar a escrita de programas corretos como “Test Units”. Por outro lado, vejo os mesmo problemas sendo repetidos constantemente. Qual o problema na definição?
Bem, sabemos que não existe fatorial de número negativo. Se a função for chamada com um número negativo, basta esperar sentado até o erro aparecer. Numeros decimais também não pode servir de argumento, pois também não seriam igualado a zero se possuírem algum valor diferente de zero nas casa decimais. Como a inferência é feita automaticamente, a linguagem assume um valor numérico que não significa necessariamente inteiro.
Para que a função aceite apenas número inteiro, basta colocar a assinatura na função. A adição de mais um teste eliminaria o problema dos números negativos. O resultado poderia ser:
fact :: Int -> Int
fact n | n < 0 = error("Não existe fatorial de número negativo!")
| n == 0 = 1
| otherwise = n * fac(n-1)
Tudo ao alcance da mão. Só ficou bem maior pelo tamanho da mensagem de erro. Mas você pode abreviar para “Err:39991″ se achar interessante. :-)
Dei uma lida rápida no artigo e nos comentários e não achei nada sobre o problema. Mas encontrei outras implementações e até informações como O(n-1+x/y*z) :-)
No mais, em vez de ‘foldl’ ele poderia usar ‘product’ e a implementação utilizando listas e ‘avaliação preguiçosa’ funciona mas retorna mensagens de erro muita alienígenas. De qualquer forma, uma material que deve ser interessante de acompanhar, principalmente por possuir comentários de diversas pessoas, fato que não ocorre em um tutorial normal.