Skip to content

Instantly share code, notes, and snippets.

@VitorLuizC
Last active February 14, 2018 17:50
Show Gist options
  • Select an option

  • Save VitorLuizC/d58f580b1459da3e4f069e69441e06d6 to your computer and use it in GitHub Desktop.

Select an option

Save VitorLuizC/d58f580b1459da3e4f069e69441e06d6 to your computer and use it in GitHub Desktop.
Haskell

Anotações do Curso de Haskell

Aqui você vai encontrar todos os exercícios, anotações, insights e até comparações com código semelhante em JavaScript. Tudo relativo ao curso de Haskell do professor Marcos Castro que pode ser adquirido gratuítamente na Udemy.

Aulas

2. Somando números

Introduz a simplicidade das funções e, aparentemente, o overload das funções com Haskell.

incrementTo 0 = 0
incrementTo n = incrementTo(n - 1) + n

Esse código equivale ao seguinte código JavaScript.

const incrementTo = (n) => {
  if (n === 0)
    return 0
  return incrementTo(n - 1) + n
}

Diferenças: Overload e tipos fortes

JavaScript não é uma linguagem com tipos fortes. Ela trabalha com valores dinâmicos e por essa razão não existe overload, não há como declarar funções com o mesmo nome e argumentos diferentes o extremo oposto do Haskell que (até então nas aulas) parece usar overload pra abstrair parte da lógica da funções.

A saída para esse esse problema foi o uso da keyword if.

PS. if/else existem também no Haskell como funções. Referência de if/else na documentação do Haskell.

3. Fatorial

Demonstra novamente a simplicidade das funções Haskell com o exemplo do cálculo de fatoriais.

factorial 0 = 1
factorial 1 = 1
factorial n = factorial(n - 1) + factorial(n - 2)

Esse código equivale ao seguinte código JavaScript.

const factorial = n => {
  if (n === 0 || n === 1)
    return 1
  return factorial(n - 1) + factorial(n - 2)
}

4. Fibonacci

Sequência de Fibonacci implementada em Haskell.

fibonacci 0 = 1
fibonacci 1 = 1
fibonacci n = fibonacci(n - 1) + fibonacci(n - 2)

O mesmo código escrito em JavaScript.

const fibonacci = (n) => {
  if (n === 0 || n === 1)
    return 1
  return fibonacci(n - 1) + fibonacci(n - 2)
}

5. Utilizando guarda

Guarda é como um short-circuit, switch/case ou um if, ela valida uma condição e faz um retorno.

A sintax é bem simples, após declarar a função adiciono pipes com as condições e seus retornos e um otherwise que é semelhante ao else do if ou o default do switch/case.

quantity n | (n == 0)  = "None"
           | (n == 1)  = "One"
           | otherwise = "Many"

O mesmo exemplo escrito em JavaScript.

const quantity = (n) => {
  if (n === 0)
    return 'None'
  if (n === 1)
    return 'One'
  return 'Many'
}

Diferenças: Guardas

Não existe guarda em JavaScript. Usei if pra ter o mesmo resultado, porém poderia ter usado switch/case, um objeto usando pattern de enumerável etc.

6. Variável anônima

A forma como compreendi variáveis anônimas foi a seguinte.

São uma forma de declarar a irrelevância do valor de um argumento recebido pela função.

customAnd :: Bool -> Bool -> Bool
customAnd False _ -> False
customAnd _ False -> False
customAnd True True -> True

O mesmo exemplo em JavaScript.

const customAnd = (x, y) => {
  if (x === false)
    return false
  if (y === false)
    return false
  return true
}

Diferênças: Variáveis anônimas

É impossível usar variáveis anônimas numa notação, porque o JavaScript não usa tipagem forte e não é uma linguagem declarativa.

O exemplo é só uma reescrita do and/&& que a linguagem já provê. Usei um simples if pra obter a mesma funcionalidade no JavaScript.

PS. Haskell também tem o operador and (&&).

Sobre as comparações

Pra falar sobre o código das comparações eu tomei como exemplo o código Haskell escrito pelo professor Marcos Castro na aula 2. Fiz apenas uma pequena alteração nele. Para manter um padrão de nomenclatura, cujas funções serão escritas em camel case troquei o nome da função de "soma" pra "incrementTo".

incrementTo 0 = 0
incrementTo n = incrementTo(n - 1) + n

No início escrevi minhas comparações usando o JavaScript da forma mais funcional que consegui. Tentando deixar o mais próximo possível do Haskell, porém não é o código que escrevo no dia-a-dia e não me pareceu uma comparação válida.

const incrementTo = n => n === 0 ? 0 : incrementTo(n - 1) + n

Então decidi escrever os exemplos em duas formas, uma de forma bastante funcional usando ES2015+ e outra procedural com ES5.

const incrementTo = n => n === 0 ? 0 : incrementTo(n - 1) + n
function incrementTo (n) {
  var r;
  if (n === 0) {
    r = 0;
  } else {
    r = incrementTo(n - 1) + n;
  }
  return r;
}

Logo nos exemplos seguintes ficou trabalhoso demais e optei por escrever um misto dos dois, que de fato é muito próximo da forma como escrevo no dia-a-dia.

const incrementTo = (n) => {
  if (n === 0)
    return 0
  return incrementTo(n - 1) + n
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment