Maratona de Haskell - Décimo Dia

Fala pessoal!

Hoje vamos falar sobre duas diferentes formas de trabalhar com Pattern Matching que são let..in e case..of.

Nós já vimos um pouco sobre let..in no primeiro dia quando nós o usamos para criar “variáveis” GHCI, mas podemos usa-las levemente diferente.

let a = 5
5 * 5
25


let add a b = a + b
add 5 4
9


let add' a b = a + b in add' 5 4
9

Ao invés de usar o where nós podemos usar o let..in e colocar a “variável” no topo.

cylinder :: Double -> Double -> Double
cylinder r h =
  let
    sideArea = 2 * pi * r * h
    topArea = pi * r ^ 2
  in
    sideArea + 2 * topArea


cylinder 8 10
904.7786842338604

Diferentemente do where o let..in é uma expressão e pode ser usado em qualquer lugar, pelo outro lado ele tem scopo somente onde é definido e nós não podemos usa-lo com Guards por exemplo, Vamos ver um exemplo de onde podemos usar let..in.

4 + let b = 5 in 5 + b + 2


[let square x = x * x in (square 2, square 3, square 4)]
[(4,9,16)]

Quando dizemos que let..in é uma expressão queremos dizer que ele tem um valor e por causa disso podemos usa-lo em qualquer lugar.

Podemos usar o let..in em list comprehension também. Com let..in em list comprehension nós podemos criar variáveis que podem ser usadas no output e em tudo que venha depois da definição de let..in.

calcBMI :: [(Double, Double)] -> [Double]
calcBMI xs = [bmi | (weight, height) <- xs, let bmi = weight / height ^ 2]


calcBMI [(85, 1.81), (70, 1.9), (60, 1.5), (90, 1.8)]
[25.94548395958609,19.390581717451525,26.666666666666668,27.777777777777775]


getOverweight :: [(Double, Double)] -> [Double]
getOverweight xs = [bmi | (weight, height) <- xs, let bmi = weight / height ^ 2, bmi > 25.0]


getOverweight [(85, 1.81), (70, 1.9), (60, 1.5), (90, 1.8)]
[25.94548395958609,26.666666666666668,27.777777777777775]

Neste caso não necessitamos funções auxiliares para nossas list comprehension.

Haskell tem uma forma diferente para fazer Pattern Matching que é o case..of. Ambos fazem o mesmo, mas como uma expressão case..of pode ser usado em qualquer lugar e Pattern Matching não.

head' :: [a] -> a
head' xs = case xs of
  [] -> error "empty list"
  (x:_) -> x


head' []
*** Exception: empty list


head' [1]
1


head' [1,2]
1


listType :: [a] -> String
listType xs = "This is " ++ case xs of
  [] -> "an empty list"
  [a] -> "list with a single element"
  _ -> "a list with more than one element"


listType []
"This is an empty list"


listType [1]
"This is list with a single element"


listType [1,2]
"This is a list with more than one element"

Com o case..of nós podemos criar uma função com Pattern Matching ou adiciona-la dentro de outras expressões.


Hoje vimos outras possibilidades para trabalhar com listas e às vezes não usar Pattern Matching. Com esse conteúdo nós finalizamos o terceiro capítulo do livro “Learn You a Haskell for Great Good!: A Beginner’s Guide”.

Written on December 10, 2016