Este documento se refere ao exercício 1 da LE1, que pode ser encontrado neste documento.
No começo do arquivo, defino a interface pública:
module LE1.Cilindro
( fromTuple
, getAltura
, getRaio
, calcArea
, calcVolume
, vazio
, isVazio
, valido
, toTuple
) where
Exporto apenas as funções que serão acessíveis aos outros módulos e
mantenho privado, em especial, a estrututra do TAD
.
Primeiro, defino o TAD
e seus construtores de tipos:
type Altura = Double
type Raio = Double
type Area = Double
type Volume = Double
data Cilindro = Vazio | Cilindro { raio :: Raio
, altura :: Altura
} deriving (Show, Eq)
Nas primeiras linhas, defino apelidos para o tipo Double
para deixar mais legível as implementações.
Após isso, defino de fato o TAD
, que possui 2 construtores de tipo:
Vazio
-> representa umCilindro
não definido ou “inválido” matematicamenteCilindro
-> oCilindro
de fato, que possui um raio e uma altura
Digo que esse TAD deriva das classes de tipo, Show
, Eq
e Ord
. Em outras palavras,
isso me permite, respectivamente:
- Imprimir na tela um
TAD Cilindro
- Verificar se um
Cilindro
é igual ou diferente de outro
Essas são as funções explicitamente pedididas no exercício:
Funções que lidam com um Cilindro
vazio
vazio :: Cilindro
vazio = Vazio
isVazio :: Cilindro -> Bool
isVazio Vazio = True
isVazio _ = False
Funções para recuperar apenas a Altura
ou apenas o Raio
de um Cilindro
. Utilizo a Mônada Maybe
Na Filosofia uma Mônada, do grego monas "unit"
, é uma substância individualmente elementar que reflete
uma dada ordem do mundo da qual propriedades materiais são derivados.
Já na Programação Funcional, uma Mônada é uma abstração que permite estruturar programas de forma genérica. Essa abstração é utilizada para evitar código clichê necessário para a lógica do programa.
Neste caso, a Mônada Maybe
possui dois construtores: Nothing
e Just <value>
.
O Nothing
representa o vazio, ou que algum processamento falhou, porém não há necessidade de lançar uma exeção
ou parar o programa por inteiro.
Já o Just <value>
envolve um valor que foi corretamente computado e significa que houve êxito.
getAltura :: Cilindro -> Maybe Altura
getAltura Vazio = Nothing
getAltura (Cilindro _ a) = Just a
getRaio :: Cilindro -> Maybe Raio
getRaio Vazio = Nothing
getRaio (Cilindro r _) = Just r
O cálculo da área de um Cilindro
é definido por: A = 2πr^2 + h(2πr)
. Isolando o termo em comum,
a fórmula pode ser simplificada, resultando em: A = 2πr(r + h)
calcArea :: Cilindro -> Maybe Area
calcArea Vazio = Nothing
calcArea (Cilindro r a) = Just area
where area = (*) (r + a) . twice $ (*) pi r
Já o cálculo do volume de um Cilindro
é definido por: V = πr^2h
calcVolume :: Cilindro -> Maybe Volume
calcVolume Vazio = Nothing
calcVolume (Cilindro r a) = Just volume
where volume = pi * (r * r) * a
Funções para se adequar aos padrões da linguagem, oferecer uma compatibilidade entre outras estruturas de dados ou que tornam a implementação das funções principais mais legível.
Funções que convertem de um 2d-Tupla
, ou Par
de Double
para um Cilindro
ou
vice-versa
fromTuple :: (Double, Double) -> Cilindro
fromTuple (r, a) = Cilindro r a
toTuple :: Cilindro -> Maybe (Double, Double)
toTuple Vazio = Nothing
toTuple (Cilindro r a) = Just (r, a)
Apenas uma função que dobra o parâmetro
twice :: Floating a => a -> a
twice x = 2 * x