1 |
ALLEF KRISTIAN TAVARES ROCHA |
# Resumo Semana 4
## Novos Tipos (type)
Cria um apelido para certo tipo.
Exemplos:
type String = [Char]
type Assoc k v = [(k, v)] -- tipo parametrizado
* Não cria tipos recursivos.
## Dados Algébricos (data)
Não são apelidos, são tipos novos
### Tipo Soma
Exemplo:
data Dir = Norte | Sul | Lest | Oeste
-- Dir pode assumir um dos 4 valores
### Tipo Produto
Exemplos:
data Ponto = MkPonto Double Double deriving (Show)
-- MkPonto: construtor (função) usada para criar um novo tipo MkPonto
-- Double Double: tipos que ele encapsula
-- deriving: derivado de outra classe
* tipos parametrizados:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
* mistura Soma-Produto:
data Forma = Circulo Ponto Double
| Retangulo Ponto Double Double
## newtype
- Define um novo tipo.
- Em tempo de compilação, é subtituido pelo sinônimo, garantindo a checagem de tipo.
## Tipos recursivos
Exemplo:
data Tree a = Leaf a | Node (Tree a) a (Tree a)
### Record Type
Exemplo:
data Ponto3D = Ponto {
_x :: Double,
_y :: Double,
_z :: Double
}
-- _x p1 = valor de x do ponto p1
## Zippers
Estruturas que trazem benefícios para o uso de estruturas atravessáveis.
Com zipper, é possível caminhar em algumas estruturas de dados em tempo constante,
armazenando o histórico e o foco atual do percurso pela estrutura.
## Classes de Tipo
- Tipo: coleção de valores relacionados.
- Classe: coleção de tipos que dão suporte a certas funções.
- Métodos: funções requisitos da classe.
- Instância: tipo que pertence a determinada classe
### Instancias (instance)
Uma instância nada mais é do que dizer que um tipo pertence a uma classe.
Este deve cumprir os requisitos mínimostipo.
Exemplo:
instance Eq Bool where
False == False = True
True == True = True
_ == _ = False
|
3 |
ANDRE RICCA YOSHIDA |
Definindo novos tipos:
Haskell nos permite declarar novos tipos, que podem ser usados como parametros de funções. A vantagem de declarar novos tipos, é deixar mais claro e didático, além de facilitar o desenvolvimento.
Um exemplo prático que aprendemos em aula, foi a inserção de informações sobre um produto em uma função. Seria necessário declararmos os tipos de entrada como String (Nome do produto), Integer (Valor) e Double (Identificador),
porém, a leitura ficaria dificil, pois não teria como identificar que se trata de um produto apenas sabendo os tipos de entrada e saída.
É nesse ponto que seria útil definir um novo tipo:
type Produto = (Integer, String, Double)
Assim, poderiamos receber como parametro de uma função CadastroProduro, apenas o novo tipo Produto.
O uso do type nos abre um leque de opções bem interessante, pois nos possibilita a criação de tipos que contém diversos parâmetros como String, Variáveis, Lista...
Após vermos a criação de novos tipos, que tem a função de dar um "apelido" a um conjunto de parâmetros, partimos para um ponto mais avançado chamado de TDA.
Tipos de Dados Algébricos
Podem conter os tipos, mencionados no parágrafo acima e permite expressividade. É um type onde especificamos o shape de cada elemento.
O termo "Algébricos" se refere a Soma e Produto, que são os dois modelos declarativos de TDA.
Soma, exemplo com Bool:
- data Bool = True | False
Produto, exemplo com construtor:
- data Ponto = MkPonto Double Double
Um construtor é uma declaração implicita de uma função usada pra criar o valor tipo.
Não podemos esquecer do "Deriving" no final da declaração do novo tipo.
É possível misturar os tipos de soma e produto.
Um ponto interessante do TDA é que em sua criação podemos usar alguns tipos pré existentes na linguagem, por exemplo o Either.
Esse tipo permite que uma função retorne dois tipos diferentes, dependendo da situação:
data Either a b = Left a | Right b
Podemos também, utilizar tipos recursivos junto com TDA, fazendo, por exemplo, uma árvore binária. |
2 |
ANDRÉ ANDERSON DE JESUS OLIVEIRA |
|
4 |
ANGELO MAEDA ROJAS |
Types
type é apenas um apelido para facilitar na compreensão das funções.
Data – Tipos de dados algébricos
Com esses tipos de dados é possível criar tipos novos, conter tipos primitivos, permite expressividade e permite checagem em tempo de compilação
Soma
data Dir = Norte | Sul | Leste | Oeste
O tipo Dir, que foi criado acima, pode conter 4 valores.
Produto
data Ponto = MkPonto Double Double
o Tipo Ponto pode conter diversos valores, em duplas, de Double que vão estar “envelopados” no MkPonto
Newtype
Cria um tipo que permite apenas um construtor
newtype Nat = N Int
Tipos recursivos
É um tipo que possui ele mesmo, seguindo a lógica de função recursiva. Segue exemplo abaixo
data Tree a = Leaf a | Node (Tree a) a (Tree a)
É um tipo que recebe uma folha “a” ou um nó que possui 2 árvores do mesmo tipo e um valor.
Álgebra de tipos
Os tipos algébricos apresentam algumas similaridades com a Álgebra matemática. Por isso a definição de tipo soma e tipo produto.
Zippers
Podemos criar tipos que auxiliem no deslocamento em estruturas, como listas ou árvores. Segue o exemplo abaixo de um zipper de lista
data Zipper a = Z [a] [a]
focus :: Zipper a -> a
focus (Z _ []) = error "Lista vazia!"
focus (Z _ (x:xs)) = x
walkRight, walkLeft :: Zipper a -> Zipper a
walkRight (Z lft (x:rgt)) = Z (x:lft) rgt
walkLeft (Z (x:lft) rgt) = Z lft (x:rgt)
Com o zipper acima conseguimos percorrer a lista facilmente, tanto para esquerda como para direita.
Classes de tipos
Nas classes de tipos podemos definir funções padrões para diferentes tipos de dados, com o uso de instância.
|
7 |
BRUNA ISHIDA |
Há a possibilidade de adicionar Data,que são dados novos, sendo possível conter tipos primitivos,
alé de permitirem expressividade e verificação do tempo de execução.
Dentro desse Data, existem:
- tipo soma, que adicionam valores muito parecidos com enums utilizados em outras linguagens,
sendo possível adicionar funções para cada um dos casos de Data
- tipo produto, possuem como valor um contrutor e os tipos primitivos que esse construtor recebe.
para sua utilização, deve-se passar o nome do contrutor com os dados do tipo primitivo
- tipos recursivos, possuem o contrutor com o tipo e possuem a metodologia para o contrutor da recursao tambem
Existe a álgebra para os tipos, sendo remetidos os tipos soma e produto para essas funções algébricas.
Assim, é possível definir que tipo de retorno e alteração de dados cada um dos Data dentro do tipo realizará.
O Zipper trás a possibilidade de "andar" e passear pelos valores existentes em uma lista, é possível utilizando
uma metodologia muito parecida com as Tree. Por exemplo, para andar para a direita, deve-se visualizar o foco atual
e colocar o filho esquerdo como novo foco.
Podemos ter também classes de tipo, são classes que definem grupos de tipos que possuem algum método documentado.
Há a possibilidade de ter classes da igualdade, de ordem, imprimíveis, legíveis, numérica, de números inteiros,
de números racionais, número de ponto flutuante |
8 |
BRUNA MIRELLI XAVIER GONCALVES |
Criando Novos Tipos
Podemos criar tipos em Haskell para atender certas demandas e facilitar a alimentação
e retorno de funções, e prover formas novas e mais práticas para lidar com certos tipos de dados
já existentes, que são a base para a criação dos novos tipos.
Tipos de Dados Algébricos
São tipos novos contendo tipos primitivos ou criando novos valores pra tipos. Permite a
criação de programas mais expressivos.
-- Tipo Soma : União (soma) de diferentes valores separados por pipe.
-- Tipo Produto: Cada valor contém X combinações de valores de um tipo.
-- Tipos paramétricos: Tipos criados com data utilizando parâmetros de tipos.
-- Tipos Recursivos: Fazem referencia a eles mesmos como em data Lista a = Vazia | Cons a (Lista a)
-- Funções úteis:
> type > Cria apelido de tipo. Sem custo computacional extra.
> data > Cria novo tipo. Possui mais segurança, tem custo computacional.
> newtype > Cria novo tipo com apenas 1 construtor. Tem segurança e não causa custo extra.
Álgebra dos Tipos
Construção de elementos algébricos que proporcionam possibilidade de operações algébricas
entre tipos, como o Void e () - unit, que são como Zero e Um.
> Either: União disjunta do conjunto, usado como tipo soma.
> Pair: Usado como construção genérica para um tipo produto.
Zippers
Estrutura que traz benefícios para o uso de estruturas atravessáveis, como caminhar nas
duas direções em uma lista e atravessar árvores.
Classes de Tipo
Definem grupos de tipos que devem ser passíveis de serem aplicados ou conterem algumas
funções. Suas instâncias definem o funcionamento dessas funções. Exemplos de classes:
-Igualdade e desigualdade: Eq
-Operadores de ordem mais Eq: Ord
-Valores imprimíveis: Show
-Valores legíveis: Read
-Valores numéricos: Num
-Tipos de números inteiros: Integral
-Tipos de números racionais: Fractional
-Tipos de números de ponto flutuante: Floating
-Funções de enumeração: Enum |
9 |
BRUNO STORER FRANCO MARTINS |
Nessa semana aprendemos mais sobre tipos em haskell.
Através da palavra reservada type somos capazes de declarar tipos, podemos escolher nomes para esses tipos para que eles tenham contextos mais claros.
No exemplo abaixo declaramos um mesmo formato de tipo composto, mas em dois tipos diferentes (produto e cliente) para podemos
especificar em cada contexto a qual estamos nos referindo, sendo assim ambas estruturas de (Inegeder,String,Double)
nas declarações podem representar características de produtos ou clientes.
type Produto = (Integer, String, Double)
type Cliente = (Integer, String, Double)
Aprendemos alguns tipos de dados algébricos.
São eles:
1-Tipos Soma -> Permite criar um tipo que pode representar mais de um tipo diferente.
Abaixo Dir representa qualquer um dos 4 tipos Norte, Sul , Leste e Oeste.
data Dir = Norte | Sul | Leste | Oeste
2-Tipos Produto -> Permite criar um tipo que encapsula mais de um tipo.
Aqui é declarado o tipo ponto que encapsula dois doubles, com MkPonto sendo um construtor.
data Ponto = MkPonto Double Double
3-Tipos Recursivos-> Tipos capazes de encapsular os próprios tipos, um exemplo são listas ou árvores binarias.
Abaixo o tipo Tree encapsula ele mesmo no uso do construtor Node.
data Tree a = Leaf a | Node (Tree a) a (Tree a)
4-Tipo Exponencial-> Tipo que define uma relação de um tipo a para um tipo b, como uma função por exemplo.
No exemplo abaixo allTrue é um tipo exponencial que estabelece um tipo que pode ser usado para uma função
que recebe um Bool e retorna um Bool.
allTrue :: Bool -> Bool
Aprendemos também sobre Zipper que são estruturas que permitem atravessar estruturas de tipos recursivos como uma listas.
Podemos declarar classes de tipos
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
Acima para um tipo pertencer à classe Eq ele precisa implementar o operador /= |
10 |
CAIO ARGENTINO DE OLIVEIRA |
- Tipos em Haskell:
- em Haskell é possível definir um novo tipo com a palavra chave 'type'
- a palavra chave type cria um apelido (alias) para um determinado tipo:
- Ex.:
- type Produto = (Integer, String, Double)
- type Assoc k v = [(k, v)] --- nesse caso, o tipo possuí parâmetros, que podem ser especificados ao usar o tipo como "Assoc Int String" ou deixados como genérico ou com restrição de tipo
- Tipos de Dados Algébricos (ADT)
- tipo soma
- data Dir = Norte | Sul | Leste | Oeste deriving Show
- tipo produto
- data Ponto = MkPonto Double Double (MkPonto é o construtor de um valor do tipo Ponto, funcionando como uma função que recebe dois Double e retorna um Ponto)
- podemos ter tipos compostos por tipo soma e tipo produto: data Forma = Circulo Ponto Double | Retangulo Ponto Double Double
- tipo parametrizado
- data Ponto a = MkPonto a a
- data Identidade a = Id a
- data Maybe a = Nothing | Just a
- data Either a b = Left a | Right b
- tipo recursivo
- data Lista a = Vazia | Cons a (Lista a)
- data Tree a = Leaf a | Node (Tree a) a (Tree a)
- tipo exponencial:
- data Funcao a b = F (a -> b)
- Newtype
- cria um alias assim como o type mas para apenas um construtor, porém não cria um tipo novo na memória
- newtype Identidade = Id Int
- Record type
- cada tipo dentro de {} passa a ter uma função que recebem um Ponto3D e retornam um Double
- data Ponto3D = Ponto { coordX :: Double, coordX :: Double, coordX :: Double } deriving Show
- Classes de tipos
- class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
x == y = not (x /= y)
- instance Eq Bool' where
Falso == Falso = True
Verdadeiro == Verdadeiro = True
_ == _ = False
|
6 |
CAIO HENRIQUE DOS SANTOS RIBEIRO |
|
11 |
DANIEL ESPINDOLA DA SILVA |
Declaração de Tipos:
Type: Haskell permite que declaremos tipos com a keyword Type, por exemplo: “type Vetor3D = (Double, Double, Double). Isso funciona por substituição, ou seja, ao compilar o código Haskell substituirá todas as instâncias de Vetor3D por (Double, Double, Double).
Data: Uma forma mais robusta de criar tipos é através da keyword Data. Isso nos permite criar tipos Soma, que definem uma quantidade de valores diferentes que o tipo pode assumir; Produto: Pode ter vários tipos ao mesmo tempo; Recursivo: É um tipo que depende de recursão na sua definição, por exemplo a definição de lista.; exponencial é o tipo que tem uma quantidade a^b de definições possíveis.
Álgebra de tipos:
Através das 4 definições de Tipos Data é possível utilizar as regras de álgebra nos tipos de haskell. O Void é utilizado como zero, () é utilizado como Um, Either é utilizado pra definir a soma, Pair para o produto.
Zipper:
O Zipper é uma estrutura que nos permite utilizar da álgebra dos tipos para otimizar certas operações que sem ela seriam custosas, no caso das listas ele funciona dividindo a lista em duas, uma que contém o elemento foco e os seguintes e outra que contém os elementos anteriores ao foco.
Classes de Tipos:
É uma coleção de tipos, contém métodos que são aplicáveis para os tipos daquela classe e que podem ser definidos utilizando instâncias para cada tipo.
|
13 |
DIEGO SOUSA SANTOS |
|
62 |
DIOGO AKIO BALBONI MIYAKE |
|
14 |
EDUARDO MACIEL DE SOUZA |
Nessa semana pudemos estudar com profundidade os tipos em Haskell. Passando pelos seguintes tópicos:
- Criação de novos tipos: Vimos que os tipos que criamos podem ser enquadrados em 3 diferentes grupos: Soma, Produto e Recursivo. Além de vermos as diferenças entre as palavras chaves 'data', 'type' e 'newtype'.
- Álgebra de tipos: Vimos os Tipos de Dados Algébricos (ADTs em Inglês), que possuem semelhanças com a algebra matemática, pois podemos representar esses tipos matemáticamente e realizar simplificações.
- Zippers: Quando queremos navegar por dentro de um tipo, como uma lista ou árvore, podemos usar das técnicas matemáticas, como a derivação, para encontrarmos uma função que nos diga algo sobre um ponto específico, um "foco" da lista. Assim, podemos escrever essa função como um tipo e navegar mais facilmente pelas estruturas de dados.
- Classes de Tipo: Descobrimos que as palavras classe, instância, método e tipo, possuem significados distintos quando falamos de Haskell ou sobre o paradigma de orientação a objetos. Em Haskell uma classe trata-se de uma coleção de tipos e os métodos são funções da classe. Podemos 'herdar' de outras classes de tipos, trazendo seus métodos para o nosso tipo.
As classes que foram abordadas em aula foram: Eq - igualdade, Ord - Odenáveis, Show - imprimíveis, Read - legíveis, Num - tipos numéricos, Integral - Inteiros, Fractional - racionais e Floating - ponto Flutuante. E por fim o comando :info que podemos usar para adquirir mais informações sobre os tipos e classes. |
15 |
EUGENIO VERAS MARIA |
|
16 |
FABIO DOS SANTOS DE SOUZA |
Nessa quarta semana da disciplina de paradigmas de programação, fomos introduzidos na criação de novos tipos de dados em Haskell. Primeiramente, analisamos com base num estudo de caso, que realmente existe a necessidade de se criar novos tipos. Em seguida, aprendemos a apelidar um tipo, com a declaração “type”, o que permite obtermos um código mais legível, porém essa abordagem possui problemas relacionados à coesão.
Após isso, conhecemos os tipos de dados algébricos, chamados assim porque possuem propriedades algébricas elementares, como (x+x) = 2*x; e são a base da criação de novos tipos de dados no Haskell. Os TDAs podem conter tipos primitivos e são classificados da seguinte maneira :
*Tipos Somas - aqueles que podem ser atribuídos a ( X1 + X2 + X3 … ) valores distintos, onde Xi representa a quantidade de valores possíveis para o campo i, por exemplo: data Bool = True | False, soma = 2.
*Tipos Produtos - aqueles que podem ser atribuídos a ( X1 * X2 * X3 … ) valores distintos, onde Xi representa a quantidade de valores possíveis para o campo i, por exemplo: data Teste = Teste Bool Bool, produto = 4.
**Observação: podemos misturar as ideias desses dois tipos, criando tipos ainda mais complexos.
*Tipos Recursivos - são os tipos que são usados em sua própria declaração de tipos, por exemplo, data Arvore = Leaf Int | Node ( Arvore Int ) Int ( Arvore Int ), este tipo descreve estruturas naturalmente recursivas.
*Tipos Exponenciais - as funções também são tipos, e sabemos que uma função f:A->B, admite B^A valores distintos, logo, há B^A definições de funções diferentes.
Além disso, estudamos Classes de tipos, que são coleções para agrupar tipos que compartilham algum método, vimos como definir uma classe e como instanciá-la. Em seguida, nos aprofundamos nas classes que já estão presentes no Haskell, como : Eq, Ord, Show, Read, Num, Integral, Fractional, Floating, Enum.
|
50 |
FELIPE AUGUSTO FLOR DE SOUZA |
Para criar um tipo se utilizar o type;
Tipos de dados algébricos: Tipo novos contendo tipos primitivos ou criando novos valores;
Tipo soma: Tipo formado pela união de diferentes valores (Exemplo data bool = True | False )
Tipo produto: Tipo formado por dois valores de tipo iguais (Exemplo data Ponto = MkPonto Double Double)
Tipo Recursivo: São tipos que são definidos usando o próprio tipo que você define (Ex: data Lista a = Vazia | Cons a (Lista a) )
Tipos de Dados Algébricos tem similaridade com a Álgebra;
|
18 |
FELIPE DE SOUZA TIOZO |
Nesta ultima aula aprendemos principalmente sobre diferentes tipos de dados. Um exemplo é quando temos parametros iguais do mesmo tipo em uma função, então como fazer para separar-los de uma forma que a assinatura da função faça sentido para alguém que está lendo, no caso, podemos usar os `type`s. Outro assunto que tivemos foi sobre os tipos de dados algébricos, dentre eles temos soma, produto etc.
|
19 |
FELIPE OLIVEIRA SILVA |
Durante a semana 4, foi abordado o assunto de "Tipos de Dados algébricos", também conhecidos como ADTs. Em Haskell, podemos criar uma diferenciação entre tipos idênticos com contexto diferente,
criando novos tipos compostos de tipos elementares. Dentro dos ADTs, podemos classificá-los sendo:
- Tipos completamente novos;
- Pode conter tipos primitivos;
- Permite expressividade;
- Permite checagem em tempo de compilação;
Dentro dos ADTs, temos também os Zippers, que podem ser definidos como uma operação de derivada dentro dos tipos algebrícos, além das operações de adição, multiplicação e exponenciação.
|
17 |
FELIPE PONSANO FRANKE |
Para melhor organizar seu código, é possível criar tipos (type) em haskell. O tipo nada mais é
que um "apelido" de um tipo já existente em haskell. Pode se chamar uma tupla com um nome definido por
você para facilitar a leitura. O tipo, no entanto, não filtra nada quando usado em funções.
Vamos supor que eu tenha um tipo TuplaA que recebe dois ints e um tipo TuplaB que recebe dois ints tambem
Posso passar uma TuplaB no lugar de uma TuplaA e vice versa.
Para evitar isso, é possível criar um novo data type. O data type é de fato um tipo de dado
e não apenas um nome conveniente.
Há varios tipos de data types. Os usados nessa lista foram os tipos soma, que são do tipo
data novoTipo = Tipo1 | Tipo2 | Tipo3 ...
Uma instancia dessas pode assumir apenas um dos tipos.
Outro são os tipos produto. Nele deve haver necessariamente todos os tipos descritos para ser válida
a instância.
ex: data novoTipo = Construtor tipo1 tipo2
Esses tipos tem esses nomes devido ao número de possibilidades de tipos dentro deles.
Com esses tipos é possível validar dados muito mais eficientemente. É possível também criar
Zíperes, que auxiliam a hor de correr uma lista ligada, funções maybe, que facilitam na hora de
devolver um erro, funções either, etc
Dois tipos notáveis de datatypes são o void e o unity. Não foi especificado exatamente como
esses tipos podem ser utilizados, mas tomamos em boa fé que são uteis para aumentar a segurança
do código.
|
25 |
GABRIEL ALBANO SANTOS |
## Criando apelidos de tipos com type
Em Haskell, com o uso da palavra `types` podemos criar um apelido para determinado tipo, o que é muito útil para deixar as assinaturas de funções mais fáceis de serem interpretadas. Ao criar esse tipo novo podemos também criar funções auxiliares.
Em alguns casos, sem o uso de type, seria díficil de distinguir as diferentes entradas na assinatura da função. Podemos criar um array associativo (dicionário) e uma função find que recebe como parâmetro uma chave, um array associativo, e retorna o primeiro valor encontrado correspondente a essa chave. Nesse caso, é importante o uso da restrição Eq para indicar que a função só pode receber valores k que podem ser comparados por igualdade.
## Tipos de dados algébricos
São tipos novos que podem conter tipos primitivos ou novos valores para tipos. Permite maior expressividade e checagem em tempo de combilação.
### Tipo Soma
Tipo formado pela união de diferentes valores.
Podemos criar, por exemplo, a função `para` , que recebe um tipo de dado criado chamado `Dir` , e retorna o apelido de tipo `Passo`
### Tipo Produto
Tipo caracterizado pela quantidade possíveis de valores que podem ser representados por esse tipo, que é igual à quantidade da combinação dos tipos primitivos utilizados para criar esse tipo.
### Tipos Parametrizados
Podemos inserir parâmetros na criação de tipos para termos melhor controle sobre o tipo resultante. Com o uso do Maybe, podemos apontar que um tipo pode retornar algum valor ou não retornar nada. Com o Either, podemos apontar que um tipo pode retornar dois tipos diferentes.
Classes de Tipos
As classes de tipos definem grupos de tipos que devem poder implementar certos tipos de funções ou dados. Podemos criar classes com a keyword class, e criar instâncias de classes com a keyword instance.
|
26 |
GABRIEL BELLOMI MEALE |
Como criar novos tipos:
type x == (y, z) // Funciona como uma espécie de struct do C. Porém o novo tipo criado com "type" é traduzido pelo compilador para os tipos primitivos, o que pode não ser muito útil quando desejamos especificar corretamente o que uma função deve fazer com esse novo tipo.
data Dir = Norte | Sul // de fato cria um novo tipo, porém esse ocupa mais espaço na memória.
newtype - cria um novo tipo, nao causa overhead extra nem custo de memoria igual o data, e nesse sentido é igual ao type. Limitações: apenas um único construtor, não da pra fazer o tipo Soma
recordType - cria funções auxiliares para retornar certos campos do tipo.
deriving - Quando criado um novo tipo, podemos receber como se fosse uma herança, a partir de deriving, utilizadas para esse novo tipo como: equidade, ordenação, mostrar, ler, etc
Polimorfismo paramétrico torna a programação segura.
tipo soma - separado por pipe
tipo maybe
tipo either
Zippers - permitem, por exemplo, que naveguemos numa lista sempre como O(1) ao inves de O(n).
Classes de tipo - Servem para criar uma nova classe dá suporte a novas funções ou operadores.
Instanciar uma classe para cada tipo de dado especifico e seus comportamentos, a partir de uma classe de tipo
|
20 |
GABRIEL DE MELLO FIALI |
Apelidos de tipos:
type <nome> = <conteúdo>
Tornam o funcionamento de funções mais claro e informativo, mas não necessariamente restringem o recebimento de parâmetros às entradas corretas.
Permite tanto especificar os valores de tipo quanto deixar os mesmos como genéricos.
Não permite a criação de apelidos recursivos.
Tipos de Dados Algébricos:
data <Nome> = <conteúdo>
Restringe o recebimento de parâmetros, não sendo intercambiáveis.
Diretiva "deriving": compilador cria instâncias de classes de tipos automaticamente.
newtype <Nome> = <conteúdo>
Permite apenas um construtor e requere a tipagem específicada, sem causar overhead extra no processamento e uso de memória.
*Record Type: simplifica definições de funções ao as embutir na própria definição do tipo.
SOMA: Tipo com valores bem especificados. A quantidade de valores possíveis corresponde à soma das quantidades dos valores separados por pipe.
PRODUTO: Recorre a um construtor, envelopando mais de um argumento. A quantidade de valores possíveis consiste no produto dos valores referenciados após o construtor.
RECURSIVO: Recorre a chamadas do próprio tipo.
EXPONENCIAL: Permite definir uma função. A quantidade de valores possíveis consiste na exponenciação dos valores dos parâmetros de entrada.
*Maybe: Permite especificar valores opcionais com os construtores Nothing e Just <tipo>. Útil para operações que nem sempre retornam um mesmo tipo de valor e para fazer tratamento de erros (com uso da construção "case").
*Either: Permite que funções possam retornar dois tipos diferentes dependendo do caso. Também útil no tratamento de erros, sem interromper a execução.
Algebra de Tipos:
Tipos sem valor definido: Void
Tipos com valor novo, mas não especificado: ()
Podem ser utilizados como base para verificar propriedades algébricas, como por exemplo distributividade.
Zipper:
Estrutura de dados que permite acesso em tempo constante.
Pode ser utilizado para listas ou árvores, seccionando-as.
Classes de tipos:
Coleções de tipos que contém métodos e são instanciadas para tipos específicos. |
23 |
GABRIEL MENDONÇA FARIAS |
Em Haskell existem tipos, tal como Bool, Int, Char, etc. Que recebem valores e assumem que estes valores contem um determinado padrão e podem ser usados de diferentes formas nas funções, como por exemplo Bool retorna True ou False a depender da resposta da função, enquanto Int será um número inteiro. Sendo assim é possível criar tipos para realizar diferentes tarefas com base na necessidade.
Os novos tipos, são feitos usando como base os tipos já implementados na linguagem Haskell, mas podem facilitar tarefas na entrada, saída e organização dos dados. Para isso, pode-se usar a palavra type, seguida do nome do novo tipo e inserindo na sequência os tipos que este novo tipo receberá.
Também é possível criar tipos usando a palavra data seguida pelo nome do tipo e as possíveis saídas que ele pode assumir. Neste caso, é possível criar saídas com nomes completamente novos (tipo soma), além de poder usar construtores junto aos tipos já estabelecidos para criar um envelope (tipo produto). Permitindo por exemplo, declarar que o nome do envelope (que é uma declaração implícita do tipo) receberá uma entrada composta por dois valores de outro determinado tipo.
Também é possível utilizar os novos tipos, para criar outros e inclusive misturar os tipos soma e produto nas novas criações.
Com a criação de novos tipos, é possível desenvolver dentro do próprio programa setores que verificam algumas possibilidades de erro, como verificar se há uma entrada vazia ou retornando tipos diferentes a depender da situação, com o uso das funções case e Either.
|
24 |
GABRIEL MURAKAMI ALVES |
Tipos de Dados)
Para facilitar o uso de entradas de funções que possuem mais de um tipo, existe
o método `type` que possibilita a criação de um apelido de tipos personalizados,
como por exemplo `type Produto = (Integer, String, Double)`. Porém não é possível
construir apelidos recursivos. Agora para realmente gerar um novo tipo existe
o método `data`. Para o método `data` podemos tanto definir os demais tipos dentro
do mesmo, tanto definir um parâmetro que definirá os tipos. Esse tipo é chamado
de paramétrico.
Dois tipos paramétricos interessantes e muito usados são o `Maybe` e `Either`.
O primeiro serve para retornar um único valor ou nada, e o segundo para retornar
um ou outro valor.
Para finalizar temos como definir classes de tipos, que nos permite gerar instâncias
derivando o comportamento da mesma para outros tipos, em uma espécie de herança
de classe, em que a instância possui o mesmo método que a classe pai, porém
sobrescrita com uma regra específica.
|
31 |
GABRIEL RIOS SOUZA |
Tipos Compostos:
- Em Haskell, uma forma de criar um tipo é com a palavra-chave type (type cria apenas um apelido para um certo tipo)
- Exemplo:
type Produto = (Integer, String, Double)
- Outro exemplo de tipo que já utilizamos e que é um apelido é a String:
type String = [Char]
- Podemos também criar tipos paramétricos (com uma ou mais variáveis de tipo em aberto):
type Assoc k v = [(k,v)]
find :: Eq k => k -> Assoc k v -> v
find k t = head [v | (k',v) <- t, k == k']
Tipos de Dados Algébricos:
- Tipos completamente novos.
- Pode conter tipos primitivos.
- Permite checagem em tempo de compilação
- Categorias (Soma, Produto, Recursivo, Exponencial)
- Tipo Soma:
data Bool = True | False
data: declara que é um novo tipo
Bool: nome do tipo
True | False: valores que poder assumir
- Tipo Produto:
data Ponto = MkPonto Double Double
data: declara que é um novo tipo
Ponto: nome do tipo
MkPonto: construtor (ou envelope) - declaração implícita de uma função usada para criar um valor do tipo Ponto
Double Double: tipos encapsulados
- OBS: O nome do tipo e o nome do construtor podem ser os mesmos!
- Para ser possível imprimir esse tipo:
data Ponto = MkPonto Double Double
deriving (Show)
deriving: derivado de outra classe
Show: tipo imprimível
Haskell cria uma instância da função show para esse tipo de dado.
- tipo Maybe (tipo parametrizados):
maybeDiv :: Int -> Int -> Maybe Int
maybeDiv _ 0 = Nothing
maybeDiv m n = Just (m `div` n)
- tipo Either:
data Either a b = Left a | Right b
- Criar um novo tipo com a função newtype:
- Permite apenas um construtor
newtype Nat = N Int
- Diferença entre newtype (novo tipo) e type (apelido)
- Diferença entre newtype (checagem em tempo de compilação) e data.
- Tipo Recursivo (Mistura do Soma com Produto):
data Tree a = Leaf a | Node (Tree a) a (Tree a)
|
22 |
GABRIEL ROSSETTO MIGLIORINI |
O recurso type ajuda na organização estética do código. Isso porque uma função do tipo:
f :: (Int, Float, Float) -> Float
pode facilmente ser conflitada com:
f1 :: (Int, Float, Float) -> Float
caso não exista uma documentação. Assim, a função do type é explicitar um apelido para um tipo existente. No mesmo exemplo teríamos:
type Universidade = (Int, Float, Float)
type Aluno = (Int, Float, Float)
E portanto:
f :: Universidade -> Float
f1 :: Aluno -> Float
Uma limitação para o type é que não pode ser aplicado a tipos mais complexos, como o recursivo. Também é possível criar tipos inteiramente novos. Exemplos seriam:
data UFABC = Professor | Aluno | TA
data Pessoa = Pessoa UFABC Int
Isso permite uma maior expressividade no código. No primeiro caso utilizamos tipos novos, enquanto no segundo construímos a partir de tipos já existentes. Um detalhe extra é que as declarações podem ser parametrizadas: Maybe e Either são dois exemplos. Sendo que o tipo Either define a soma de dois tipos ou a união disjunta do conjunto definido por dois tipos.
Diferentemente de type, data nos permite criar tipos recursivos (como árvore binária).
Utilizando os ADT's ja explicitados, também é possível criar Álgebra de tipos. A principal vantagem é que uma vez que as propriedades algébricas funcionam, é possível reestruturar nossos tipos para formas equivalentes quando for conveniente.
Por fim, é possível criar novas classes. Classes são conjuntos de tipos. As classes possuem instâncias, que são coleções de valores relacionados que pertencem àquela classe. Exemplos de classe são Num, Integral, Fractional, Floating e Enum.
|
58 |
GABRIEL SILVESTRE MANCINI |
|
29 |
GEORGE HARRISON ROCHA |
• Em Haskell existe várias formas de criar um tipo de dado;
• type: cria um apelido para um tipo;
• Pode-se também criar tipo de paramétricos;
• Tipos de Dados Algébricos: tipos completamente novos que podem conter tipos primitivos, permitem a expressividade e checagem em tempo de compilação;
- Tipo soma: declarado da seguinte forma: data nome_do_tipo = valor1 | valor2 | valor3 ...;
- Tipo produto: declarado da seguinte forma: data nome_do_tipo = construtor tipo1 tipo2 ...;
- Pode-se misturar os tipos soma e produto;
- Maybe a: tipo que indica que pode retornar nada ou retornar um valor do tipo a. Pode ser usado para controlar erros, e estes, por sua vez, podem ser capturados com a expressão case;
- Either: permite que uma função retorne dois tipos de dados diferentes, a depender da situação;
- newtype: função que permite apenas um construtor, que define um novo tipo até ser compilado, onde passa a ser um sinônimo.
• Tipos recursivos: tipos que são definidos usando o próprio tipo que se está definindo;
• Pode-se definir um tipo produto usando a sintaxe Record Type;
• Álgebra dos tipos: Os tipos de dados algébricos apresentam algumas similaridades com a álgebra matemática. Os tipos soma e produto remetem às operações algébricas;
- O tipo Zero é definido em Haskell como Void e o tipo Um é definido como ();
- o tipo Either define a soma de tipos enquanto que o tipo Pair define o produto de tipos.
• Zippers: uma aplicação da álgebra de tipos que consegue otimizar certas operações custosas;
• Classes de tipos: classes que definem grupos de tipos que contém algumas funções.
- Instâncias da Classe: uma classe pode ser formada partir da extensão de outra classe;
- Significado diferente da POO.
|
30 |
GIANCARLO KAMI DELL ARINGA VIANA |
Nesta semana o conceito de tipos de dados foi introduzido, sendo eles dividios
entre tipos de Soma, Produto, Recursivos e Exponencial. Com esses tipos podemos criar diversos formatos de tipos de dados,
e esses tipos podem derivar classes, tambem introduzidos nesta aula. Esses tipos possuem funcoes, e podem ser instancias de outros tipos.
Esses tipos de dados tambem possuem construtores, que podem ser parametrizados. |
68 |
GIOVANNA NOGUEIRA |
|
28 |
GIOVANNI ALMEIDA DE SOUSA |
1. Novos tipos:
a. Para criar um novo tipo de dado em Haskell pode-se utilizar a palavra-chave Type, por exemplo: type newDataType = (Integer, String, Float).
b. Type cria apenas um apelido para o novo tipo.
2. Tipos de Dados Algébricos
a. A função data permite a criação de tipos completamente novos, expressividade, checagem em tempo real e pode conter tipos primitivos. Por exemplo:
tipo Soma: data Estação = Verao | Inverno | Outono | Primavera
tipo Produto: data Ponto = MkPonto Double Double – onde MkPonto é um construtor, função implícita para criar um valor de tipo Ponto.
b. Para imprimir um novo tipo de dado do tipo Produto, utiliza-se as funções deriving (Show) – onde deriving refere-se a uma chamada de outra classe e Show um tipo imprimível. Para fazer uso da função, deve-se sempre envelopar a variável com o construto, exemplo:
dist (MkPonto a b) (MkPonto c d) = sqrt $ (x-x')^2 + (y-y')^2
d. Declaração de tipo parametrizável pode ser utilizado para melhor tratamento de erros e exceções, exemplo:
data Maybe a = Nothing | Just a
e. Os erros podem ser capturandos utilizando a função case, exemplo:
divComErro m n = case (maybeDiv m n) of
Nothing -> error "divisão por 0"
Just x -> x
f. A função NewType permite a criação de um novo tipo com apenas um construtor. Nesse caso um novo tipo é definido e não apenas um apelido como na função type.
3. Tipos Recursivos
a. A árvore binária é um exemplo de tipo recursivo, por exemplo:
data Tree a = Leaf a | Node (Tree a) a (Tree a)
4. Outros tipos: Zippers.
5. Declaração de novas classes de tipos: função class
6. Instâncias de classes: Eq, Ord, Show, Read, Num, Integral, Fractional, Floating...
7. Derivação de Instância: Enum
|
34 |
GUILHERME FERREIRA GALDINO |
Criação de novos tipos
- Type
Cria apenas um apelido para um determinado tipo
type Produto (Integer, String, Double)
A tupla acima tem como apelido Produto, assim poderá ser substituída em qualquer parte do código
- Tipos de Dados Algébricos
Diferente do type, realmente cria um novo tipo
A palavra chave usada é 'data'
- Tipos Soma
Forma uma coleção de tipos, podendo assumir qualquer valor dentro dela
data Dir = Norte | Sul | Leste | Oeste
- Tipos Produto
Possui um contrutor (ou envelope) que declara implicitamente uma função para criar um novo valor do tipo em questão
data Ponto = MkPonto Double Double
Para usa-lo envelopar a variável com o construtor
dist :: Ponto -> Ponto -> Double
dist (MkPonto x y) (MkPonto x' y') = sqrt $ (x-x')^2 + (y-y')^2
dist (MkPonto 1 2) (MkPonto 1 1)
As declarações também podem ser parametrizadas
data Maybe a = Nothing | Just a
maybeDiv :: Int -> Int -> Maybe Int
maybeDiv _ 0 = Nothing
maybeDiv m n = Just (m `div` n)
- newtype
Mistura do conceito de data e type. Ele define um notivo até ser compilado, mas depois é substituído como um apelido.
Além disso, ele permite apenas um construtor.
newtype Nat = N Int
Outra forma definir um tipo produto Record Type
data Ponto3D = Ponto { coordX :: Double
, coordY :: Double
, coordZ :: Double }
- Tipos Recursivos
Um tipo que chama ele mesmo. Exemplo clássico é da árvore binária.
data Tree a = Leaf a | Node (Tree a) a Node (Tree a)
- Álgebra dos tipos
Semelhante a álgebra matemática
data Zero -- não possui valor ou Void
data Um = () -- possui apenas um valor ou Unit
O tipo Bool possui apenas dois valores possíveis. Na álgebra de tipos, ele é apenas a soma de dois valores unitários.
data Bool = False | True
type Bool' = Either () ()
Either define a soma de dois tipos
data Valida_Cod = Pair Char Bool
Char possui 256 valores possíveis e Bool 2 valores possíveis.
Então, a tipo acima possui 256 * 2 = 512 valores distintios, já que é um tipo produto.
- Zippers
Tipo de estrutura boa para uso de outras estruturas atravessáveis, como listas.
data List a = Empty | Cons a (List a)
notacao algebrica => L(a) = 1 + L(a)
Derivada => L'(a) = 1 / (1 - a)²
type DiffList a = Pair (List a) (List a)
A partir de uma lista, derivando ela, conseguimos duas listas. Dessa forma, é possível caminhar na lista em qualquer direção em tempo constante.
- Classes de tipo
Definem grupos de tipos que devem conter algumas funções especificadas.
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
Isso quer dizer: para um tipo pertencer a classe Eq, ela deve ter uma implementação das funções (==) e (/=).
Além disso, ela já define um padrão de função para (/=)
- Instância da Classe
instance Eq Bool where
False == Flase = True
True == True = True
_ == _ = False
Declara que o tipo Bool pertence a classe Eq.
Apenas tipos que são definidos por data ou por newtype podem ser instâncias de uma classe.
O Haskell consegue inferir as intâncias das classes mais comuns, usando a palavra-chave 'deriving'
data Dias = Dom | Seg | Ter | Qua | Qui | Sex | Sab
deriving(Show, Enum)
Show = converte o tipo Dias em uma string -- "Dom" | "Seg" etc.
Enum = enmuera o tipo como fosse uma lista sequencial -- [Seg .. Sex] = [Seg, Ter, Qua, Qui, Sex]
|
35 |
GUILHERME FUZISAWA DE SA |
Declaração de Tipos e Classes
- Declarando com "type": Aqui podemos declarar um nome para um(ou mais) tipo existente ou um declarar um tipo entorno de outro tipo já criado.
Exemplo: type Pos = (Int, Int) e type Trans = Pos -> Pos
Porém, declarações do tipo "type" não podem ser recursivas.
- Declarando com "data": Define um tipo totalmente novo, este pode ser declarado definindo seus valores. Os valores definidos devem começar com letras maiúsculas onde são chamados de construtores. Exemplo: data Move = North | South | East | West
Além disso, podemos adicionar argumentos aos construtores quando estamos declarando o novo tipo.
Exemplo: data Shape = Circle Float | Rect Float Float
E também podemos parametrizar os próprio tipo.
Exemplo: data Maybe a = Nothing | Just a
- Declarando com "newtype": Aceita um único construtor com um argumento. A vantagem de utiliza-lo é o custo quando o programa é avaliado.
Exemplo: newtype Naturais = N Int
- Tipos recursivos: podemos declarar tipos recursivos utilizando data e newtype
Exemplo: data Tree a = Leaf a | Node (Tree a) a (Tree a)
Álgebra dos Tipos: Com os operadores Void e "()"(chamado UNIT) podemos definir os tipos Either e Pair onde são:
data Either a b = Left a | Right b
Onde Either é a soma de dois tipos
data Pair a b = (a, b)
Onde Pair é o produto de dois tipos
Zippers são estruturas que contém informações da estrutura em questão e seu "foco". É com ele que podemos focar em determinado valor e mantendo toda a informação do caminho percorrido e não percorrido até o foco.
Classes de Tipo: Grupos de tipo que possuem funções.
Aqui vimos classes de igualdade(Eq), ordem(Ord), imprimíveis(Show), legíveis(read), numérica(Num(, números inteiros(Integral), números racionais(Fractional), números de ponto flutuante(Floating).
|
36 |
GUSTAVO MATHEUS LIMA SANTOS |
|
27 |
GaMendes |
Nessa semana, começamos aprendendo a criar novos tipos na linguagem Haskell, utilizando a palavra chave type, note que type cria apenas um apelido para um certo tipo, ou seja, uma nova forma de nos referenciarmos a um determinado tipo apenas facilitando a legibilidade do código. Porém essa forma de criar novos tipos não permite criação de tipos mais complexos, como tipos recursivos, então além dessa palavra chave, também vimos como resolver esse problema com tipos algébricos, que tem como características, tipos completamente novos, poder conter tipos primitivos, permitir expressividade e checagem em tempo de compilação. Aqui aprendemos sobre o tipo maybe, que indica que um tipo Maybe a pode não ser nada ou pode ser apenas o valor de um tipo a.
Seguindo no conteúdo, vimos com criar tipos usando newType. A diferença entre newtype e type é que o primeiro define um novo tipo enquanto o segundo é um sinônimo. Já a diferença entre newtype e data é que o primeiro define um novo tipo até ser compilado, depois ele é substituído como um sinônimo. Isso ajuda a garantir a checagem de tipo em tempo de compilação.
Em álgebra de tipos vimos como os tipos de dados algébricos apresentam algumas similaridades com a álgebra matemática. Depois de passar pelo estudo de álgebra de tipos, vimos sobre zippers que são uma forma de linguagem que utiliza o contexto para o propósito de manipular localizações numa determinada estrutura de dados.
Seguindo o conteúdo, vimos sobre classes de tipos que definem grupos de tipos que devem conter algumas funções especificadas. Para criar uma nova classe de tipos utilizamos a palavra reservada class. Podemos também criar instâncias de classes, usando a palavra chave instance. Apenas tipos definidos por data e newtype podem ser instâncias de alguma classe.
|
5 |
HEITOR BELLINI |
-- Criar novos tipos
Podemos criar tipos novos em haskell utilizando o type! Ele cria um "apelido" para novos tipos:
type Produto = (Integer, String, Double)
type Cliente = (Integer, String, Double)
O tipo String também é um apelido!
type String = [Char]
Há a possibilidade de criar tipos paramétricos, que são tipos que dependem de parâmetros:
type Assoc k v = [(k,v)]
**OBS: não é possível tipos (apelidos) recursivos!
-- Tipos de dados algébricos
Cria tipos de dados reais (não apenas apelidos), com maior expressividade e checagem em tempo de compilação.
- Tipo soma:
Formado pela união de diferentes "valores", separados por pipe (ou):
data Dir = Norte | Sul | Leste | Oeste deriving Show -- deriving Show possibilita a impressão de tipos
**OBS: os "valores" devem iniciar em maiúsculas.
-- Tipo produto
Possibilita mais de um valor que é representado pelo tipo criado:
data Ponto = MkPonto Double Double deriving Show -- MkPonto encapsula Double Double
dist :: Ponto -> Ponto -> Double
dist (MkPonto x y) (MkPonto x' y') = sqrt (x-x')^2 + (y-y')^2 -- distancia entre dois pontos
-- Tipo parametrizado
É um tipo definido pelo parâmetro informado:
data Ponto a = MkPonto a a -- possibilita Double, Float, Int, etc.
Maybe é um tipo paramétrico muito utilizado:
data Maybe a = Nothing | Just a
Pode ser usado em computações que podem falhar. Exemplo Maybe + case:
maybeDiv :: Int -> Int -> Maybe Int
maybeDiv _ 0 = Nothing
maybeDiv m n = Just (m `div` n)
divComErro :: Int -> Int -> Int
divComErro m n = case (maybeDiv m n) of
Nothing -> error "divisão por 0"
Just x -> x
Tipo Either também é interessante:
data Either a b = Left a | Right b
- data + type?? SIM!
newtype cria um novo tipo com as caracteristicas de type e data, mas sem overheading (limitado à um parâmetro para apenas um construtor):
newType Identidate = Id Int
-- Tipos recursivos
São definidos o pŕoprio tipo que estamos definindo. Ex:
data Lista a = Vazia | Cons a (Lista a)
|
37 |
HENRIQUE AUGUSTO DE OLIVEIRA |
Um grande problema encontrado é quando uma função precisa receber outras duas funções diferentes e ambas possuem parâmetros semelhantes, mas que, no conceito, apresentam significados diferentes. Como ambas podem ser diferenciadas? Através da criação de novos tipos. Existem algumas formas de fazer essa diferenciação.
O type define um apelido para um tipo. Um exemplo já utilizado é que String é um apelido para [Char]. Quando ocorre a compilação, é substituído para os tipos corretos e é feita a checagem.
Uma outra forma de definir um tipo é através do nome "data", que cria um novo tipo de dado.
A ideia ao criar um tipo é dar nomes intuitivos para facilitar para quem analisa.
Existem alguns tipos de dados específicos. O Tipo Soma, Tipo Produto, Tipo Recursivo e Tipo Exponencial.
Para o Tipo Soma, é utilizado o "|", que se entende como um "or". Para o Tipo Produto, é entendido o uso do "and". O Tipo Recursivo ajuda a definir um tipo dependente dele mesmo. Um exemplo, é a lista. Um Tipo Exponencial é quando se tem b^a possibilidade de um tipo. Um exemplo, é a função f :: a -> b.
Existe um recurso chamado Maybe, que auxilia na criação de novas funções que imitam funções já existentes e previne possíveis erros com o Nothing. Por exemplo, pode ser definida uma função que, ao dividir um número por zero, o retorno seja Nothing.
Pode ser definido Classes de Tipos como classes que possuem funções específicas para tratar informações. O uso de instance faz com que possamos criar instâncias específicas da nossa classe, lembrando que novas classes podem ser criadas com funções personalizadas.
Alguns exemplos de classes de tipo são Eq, Ord, Show, Read, Num e Enum, sendo que cada uma possui suas funções e especificidades. |
38 |
HENRIQUE FANTATO SILVA DE ALBUQUERQUE |
Para facilitar o entendimento, e evitar a utilização de forma errônea das variáveis, podemos criar
tipos em Haskell. Um tipo é apenas um apelido para um formato de dado, como por exemplo Strings, que é
um apelido para um vetor de Char. Mas um tipo não consegue criar dados mais complexos, como os recursivos.
Podemos usar tipos soma (Exemplo data verdadeiro = sim | nao), tipos produto (exemplo: data Exemplo = Exemplo Double Double),
newtype(que permite apenas um construtor). Também podemos definir tipos recursivos, como uma árvore binária,
declarada como (data Arvore a = Folha a | Nó ( Folha a ) a (Arvore a)), podendo a variável ser uma folha, ou um nó
contendo uma árvore à esquerda, um nó central e uma árvore à direita. Os tipos também podem ser representados algebricamente
com Either(equivalente a soma) ou Pair(equivalente ao produto).
Também podemos criar estruturas atravessáveis, utilizando Zipper. Com essa estrutura, como por exemplo uma lista,
podemos andar por dois sentidos pea lista, como se fosse uma lista duplamente ligada.
Podemos criar classes de tipo, que definem grupos de tipos que devem conter algumas funções especificadas. E para
definir o funcionamento dessas funções para os tipos, podemos criar instâncias para poder detalher melhor essas funções
para cada tipo.
|
80 |
HENRIQUE MAGRO DE SOUZA |
ADTs (Algebraic Data Types), ou traduzido para o português: tipos de dados algébricos, são tipos de dados compostos por outros tipos. Em linguagens de programação de alto nível, são as estruturas ou as classes, ou os enums, por exemplo.
Existem 4 tipos de ADT:
- Tipo Soma
- Tipo Produto
- Tipo Recursivo
- Tipo Exponencial
Basicamente o que categoriza um ADT dentro de um desses tipos, é a forma com que se obtém a quantidade máxima de valores possíveis daquele tipo. Por exemplo, no tipo Soma, cada possibilidade corresponde a 1 valor possível a mais, ou seja podemos ir somando de 1 em 1 até chegar o valor máximo. Já no tipo produto, ele é composto por tipos que podem assumir mais de um valor, sendo necessário o uso da multiplicação para obter o total de valores possíveis.
Essas ADTs são de grande utilidade pois, além de nos permitir agrupar dados, nos permite dar significado a eles, e também trabalhar melhor com eles. Por exemplo, um ADT do tipo Soma, pode conter apenas um número fixo de valores, conhecidos apenas por olhar em sua definição.
### Outros
Aprendemos a dar aliases para os nossos tipos com o "type".
Usamos o deriving para derivar de uma classe, fazendo com que nossos novos tipos derivem características desejadas. Por exemplo, ao derivar de Show, isso facilita na hora de manipular os dados e também imprimi-los na tela. |
39 |
IGOR SAWAKI |
Utilizando somente os tipos de dados básicos do Haskell, pode-se criar uma certa confusão com a ordem e os significados das assinaturas e argumentos de uma função.
Para evitar isso, podemos declarar apelidos para os tipos usando “type”, para tornar o código mais entendível e diminuir a confusão.
Além dos apelidos, podemos criar novos tipos de dados, usando “data” e um nome começando com maiúscula. “data” deve ser definido por: Nome “=” construtor parâmetro(s). Tipos paramétricos possuem parâmetros (como o "a" de “Maybe a”) na declaração do tipo.
“newtype” faz algo semelhante a data e type, porém só aceita um construtor.
Os tipos de dados algébricos tem características semelhantes à álgebra da matempatica. Estes tipos podem conter tipos primitivos nos novos tipos criados.
- Um Tipo Soma é assim definido pela quantidade de valores definidos e separados por “|”.
- Um Tipo Produto é definido por todos os valores definidos combinados. Pode ser declarado também utilizando sintaxe Record Type com “{ }”.
- Um Tipo Recursivo pode chamar a si mesmo na sua definição.
- Um Tipo Exponencial pode receber uma função como parâmetro, e tem uma quantidade exponencial relacionada aos parâmetros da função.
Utilizando “deriving” podemos instanciar os novos tipos com operações de outras typeclasses (Eq, Enum, Ord, Bounded, Show, Read).
Quanto mais restrito é a declaração dos tipos da função, mais restrito é a quantidade de funções que podemos definir com aquela mesma assinatura de função.
Podemos criar novas classes (um conjunto de tipos com mesmos comportamentos) de tipos utilizando “class”; definir os seus tipos com “data” e suas instâncias com “instance”, que serão as operações utilizadas nesta classe para um determinado tipo (como os comportamentos são implementados).
|
40 |
JANUSA MAIA DA SILVA |
|
41 |
KAREN OLIVEIRA DOS SANTOS |
|
42 |
KAROLINY DOS ANJOS PEREIRA ALVES |
|
43 |
KELVIN ALVES DOS SANTOS |
|
44 |
KLEVERSON NASCIMENTO PINTO |
|
81 |
LARISSA RODRIGUES DE ALMEIDA |
#Criando Novos Tipos
O "type" cria um apelido para um certo tipo, auxiliando na identificação do objetivo de cada componente na assinatura.
#Tipos de Dados Algébricos
O "data" possibilita a criação de novos tipos, diferentemente do "type" que apenas apelida os tipos já existentes.
Tipo Soma: cria uma função que possui opções unitárias. Isso significa que OU ele assume um tipo, OU ele assume o outro.
Tipo Produto: cria uma função que encapsula vários tipos que são utilizados juntos.
Os tipos soma e produtos podem ser utilizados em conjunto.
Newtype: é a terceira forma de criar um novo tipo. Diferentemente de type, o newtype cria um novo tipo, enquanto o type apenas apelida tipos que já existem. E de forma diferente do data, o newtype após ser compilado é susbtituído como sinônimo, fazendo com que pegue menos memória do sistema.
#Tipos Recursivos
Trata-se da criação de tipos que são acessados de forma recursiva.
Exemplo de tipos recursivos: Árvore, Lista
Record Type: sintaxe para definir um tipo produto que automaticamente cria as funções que retornam o valor daquele campo do seu tipo.
#Álgebra dos Tipos
São tipos que apresentam similaridades com a Álgebra matemática.
#Zippers
Assim como é feito na álgebra matemática com as derivadas, queremos criar um ponto de foco em um elemento de alguma lista ou árvores, para isso é utilizado o Zipper.
O Zipper trata-se de duas listas, um contendo o ponto focal e o outro contendo a lista de históricos, que podem ser recuperados quando necessário. Através dessa ferramenta, é possível caminhar para frente e para trás na lista/árvore em tempo constante.
#Classes de Tipos
As classes de tipos definem os grupos de tipos. Além disso, é possível criar métodos (funções da classe) e instância (definição dos métodos de uma classe para um tipo).
|
46 |
LEANDRO RIBEIRO DE ALMEIDA |
|
47 |
LEANDRO VICTOR FERREIRA |
|
48 |
LEONARDO SANTIAGO HAMPSHIRE |
Usamos tipos para criar uma diferenciação entre tipos identicos que possuam contextos diferentes
Ex Types:
type Coord = (Int, Int)
type Passo = Coord -> Coord
Podemos criar tipos de dados
Tipos de Soma:
O dado pode receber x valores separados por |
ex:
data Dir = Norte | Sul | Leste | Oeste
Tipos de Produto
O dado precisa de um construtor e pode conter n tipos internos
Ex:
data Ponto = MkPonto Double Double
Para imprimir esse tipo, é necessário utilizar "deriving (Show)"
Dentro de funções é necessário envelopar o a variável com o construtor
é possível misturar o tipo produto com o tipo soma, dessa forma:
data Forma = Circulo Ponto Double
| Retangulo Ponto Double Double
Obs: Usando um tipo "Maybe", é possível tratar possíveis casos de excessões.
Ex:
data Maybe a = Nothing | Just a
maybeHead :: [a] -> Maybe a
maybeHead [] = Nothing
maybeHead xs = Just (head xs)
maybeDiv :: Int -> Int -> Maybe Int
maybeDiv _ 0 = Nothing
maybeDiv m n = Just (m `div` n)
divComErro :: Int -> Int -> Int
divComErro m n = case (maybeDiv m n) of
Nothing -> error "divisão por 0"
Just x -> x
Tipos Recursivos:
data Tree a = Leaf a | Node (Tree a) a (Tree a)
deriving Show
t :: Tree Int
t = Node t1 5 t2
t1 = Node (Leaf 1) 3 (Leaf 4)
t1 = Node (Leaf 6) 7 (Leaf 9)
contem :: Eq a => Tree a -> a -> Bool
contem (Leaf y) x = x == y
contem (Node l y r) x = x == y || contem l x || contem r x
Supondo uma árvore de Busca:
contem :: Eq a => Tree a -> a -> Bool
contem (Leaf y) x = x == y
contem (Node l y r) x
| x == y = True
| x < y = contem l x
| otherwise = contem r x
Record Type
data Ponto3D = Ponto Double Double Double
CoordX (Ponto x _ _) = x
CoordY (Ponto _ y _) = x
CoordZ (Ponto _ _ z) = x
ex:
data Tree a = Leaf a
| Node { _right :: Tree a
, _value :: a
, _left :: Tree a
} deriving Show
Algebra dos Tipos
|
74 |
LOUIS PHILLIPE SARDA DUBOIS |
Criando novos tipos:
type Produto = (Integer, String, Double)
type Assoc k v = [(k,v)]
Tipos algébricos:
Soma:
data Bool = True | False
data Dir = Norte | Sul | Leste | Oeste
Produto:
data Ponto = MkPonto Double Double
Onde MkPonto é o construtor e poderia se chamar Produto (mesmo nome do tipo)
Tipo soma e produto:
data Forma = Circulo Ponto Double
| Retangulo Ponto Double Double
Maybe:
data Maybe a = Nothing | Just a
divComErro m n = case (maybeDiv m n) of
Nothing -> error "divisão por 0"
Just x -> x
Either:
data Either a b = Left a | Right b
Tipos recursivos:
data Tree a = Leaf a | Node (Tree a) a (Tree a)
Record Type:
data Ponto3D = Ponto { coordX :: Double
, coordY :: Double
, coordZ :: Double
}
Álgebra dos Tipos:
Zero e Um são definidos como Void e () (chamado de operador unit)
Zippers:
data List a = Empty | Cons a (List a)
data Zipper a = Z [a] [a]
toZipper :: [a] -> Zipper a
toZipper xs = Z [] xs
fromZipper :: Zipper a -> [a]
fromZipper (Z lft rgt) = reverse lft ++ rgt
Classes de Tipo: (grupos de tipos que devem conter funções específicas)
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
|
53 |
LUCAS AKIRA HASEGAVA |
1- Criando novos tipos
troco :: (Integer, String, Double) -> (Integer, String, Double) -> Double
troco (id_prod, nome, preco) (id_cli, nome_cli, pago) = pago - preco
type Produto = (Integer, String, Double)
type Cliente = (Integer, String, Double)
pago (_, _, p) = p
preco = pago
troco :: Produto -> Cliente -> Double
troco produto cliente = pago cliente - preco produto
Note que type cria apenas um apelido para um certo tipo
2- Tipos de Dados Algébricos
Tipo Soma
type Coord = (Int, Int)
type Passo = Coord -> Coord
data Dir = Norte | Sul | Leste | Oeste
para :: Dir -> Passo
para Norte (x,y) = (x, y + 1)
para Sul (x,y) = (x, y - 1)
para Leste (x,y) = (x + 1, y)
para Oeste (x,y) = (x - 1, y)
Tipo Produto
dist :: Ponto -> Ponto -> Double
dist (MkPonto x y) (MkPonto x' y') = sqrt $ (x-x')^2 + (y-y')^2
dist (MkPonto 1 2) (MkPonto 1 1)
Newtype
Uma terceira forma de criar um novo tipo é com a função newtype, que permite apenas um construtor:
newtype Nat = N Int
A diferença entre newtype e type é que o primeiro define um novo tipo enquanto o segundo é um sinônimo.
A diferença entre newtype e data é que o primeiro define um novo tipo até ser compilado, depois ele é substituído como um sinônimo. Isso ajuda a garantir a checagem de tipo em tempo de compilação.
3- Tipos Recursivos
data Tree a = Leaf a | Node (Tree a) a (Tree a)
contem :: Ord a => Tree a -> a -> Bool
contem (Leaf y) x = x == y
contem (Node l y r) x | x == y = True
| x < y = l `contem` x
| otherwise = r `contem` x
Record Type
data Ponto3D = Ponto { coordX :: Double
, coordY :: Double
, coordZ :: Double
}
Essa sintaxe cria automaticamente as funções coordX, coordY, coordZ que retornam o valor daquele campo do seu tipo.
4- Álgebra dos Tipos
5- Zippers
6- Classes de Tipo
class Booleanable a where
toBool :: a -> Bool
instance Booleanable Int where
toBool 0 = False
toBool _ = True
instance Booleanable [Int] where
toBool [] = False
toBool _ = True
7 - Construtores de Tipos
dobra :: Int -> Int
dobra x = 2*x
flip :: Coin -> Coin
flip Cara = Coroa
flip Coroa = Cara
dobraLista :: [Int] -> [Int]
dobraLista = map (*2)
flipLista :: [Coin] -> [Coin]
flipLista = map flip |
52 |
LUCAS BRANDAO PEREIRA |
PARADIGMAS DA PROGRAMAÇÃO
RESUMO 4
Tipos de dados Algébricos
Criando novos tipos
Ao invés de usarmos tuplas sem identificadores, podemos criar novos tipos
Para isso usamos a palavra-chave `type`
Ex: String: type String = [Char]
Ou `data`
Tipos de dados algébricos
Tipos novas que podem conter tipos primitivos, permitindo maior expressividade e checagem em tempo de compilação
`data`: Palavra-chave usada para declarar que é um novo tipo
Tipo soma
Quantidade de valores que esse tipo pode ter é a soma de todos valores especificados
Tipo produto
MK`nomeDoTipo` funciona como um construtor
data Ponto = MKPonto Double Double
Tipo parametrizado
Onde não é especificado os tipos que estão sendo usados na criação do novo tipo
Tipo recursivo
Tipo que utiliza a si mesmo para retornar o valor
ex: Tipo Lista:
data Lista a = Vazia | Cons a (Lista a)
Tipo exponencial
Caracterizada por uma função
a -> b admite b^a definições diferentes
Algebra dos tipos
São tipos que apresentam similaridades com a algebra da matemática
A princípio podem parecer meio sem caso de uso mas na prática vemos sua utilidade
Efetivamente, as definições de Tipo soma e Tipo produto remetem as operações algébricas
Ex: Data Zero
Data Um = ()
Zippers
Traz benefícios de estruturas atravessáveis
Classes de tipo
São classes que definem grupos de tipos que devem conter funções especificadas
palavra-chave: `class`
Instâncias de classe
palavra-chave: `instance`
Lembrete:
Tipo - Coleção de valores relacionados
Classe - Coleção de tipos que dão suporte a certas funções ou operadores
Métodos - Funções requisitos de uma classe
Instância - Um tipo que pertence a uma classe
|
54 |
LUCAS DAVID VADILHO |
# Semana 4
## Apelidando Tipos
`type {name} = ({estrutura})`
- Evita confusões com ordem de argumentos
- Extrair campos
- Podem ser usados como tipos em funções
- São apenas apelidos, na compilação são substituídos pela base -> gera confusão de novo? (`data` resolve)
- Não permite uso recursivo
## Tipo de Dados Algébricos
### Soma
- União de diferentes valores: `|`
```
data {Nome} = {construtor de valor} | {} | ...
deriving {}
```
### Produto
- patten matching: _envelopados_ pelo construtor de tipo
- ~ produto cartesiano da quantidade de tipos
```
data {Nome} = {construtor do tipo} tipos
deriving {}
```
### Parametrizados
- Permite a generalização dos tipos
`data Maybe a = Nothing | Just a`
`data Either a b = Left a | Right b`
### Recursivo
- Usar pattern matching para caso base e geral
Exemplo:
```haskell
data Tree a = Leaf a | Node (Tree a) a (Tree a)
t :: Tree Int
t = Node t1 1 t2
t1 = Node (Leaf 2) 3 (Leaf 4)
t2 = Node (Leaf 5) 6 (Leaf 7)
```
### Record Type
- ~Automatiza criação de funções (~ _getters_)
- Usa espaço das funções, não podemos duplicar os nomes
## Álgebra dos Tipos
- Equivalência de tipos
- Equivalência de tipos entre tipo soma e tipo produto
## Zippers
- derivar expressão do tipo, encontrar expressão algébriga e traduzir para soma e produto de tipos [complicado]
- permite percorrer _listas_ e _árvores_ de maneira mais eficiente
## Classes de Tipo
- Grupos que garantem que todos os tipos dessa classe contém a implementação de algumas funções
- `type`: coleção de valores relacionados
- `class`: coleção de tipos
- Métodos: funções de uma classe
- `instance`: definição dos métodos de uma classe para um tipo
Classes padrão: Eq, Ord, Show, Read, Num, Fractional, Float, Enum |
32 |
LUCAS MAZIM DE SOUSA |
Nesta semana vimos como construir novos tipos de dados utilizando as palavras-chave type, data e newtype. Criar novos desta maneira ajuda na legibilidade e corretude do algorimo criado, tornando a compilação mais rápida em alguns casos.
O potencial da palavra-chave `data` foi explorado analisando as tipos de dados algébricos que ele permite criar (tipos soma, produto, exponenciação), e tipos mais elaborados como os Zippers.
Nesta semana também ficou mais clara a diferença entre tipos de dados e classes de tipos, e onde eles devem aparecer na assinatura de uma função.
|
51 |
LUCAS SILVA AMORIM |
|
55 |
LUCAS YUDI FUKAZAWA CASSIN |
Criação de novos tipos de dados
Através dos tipos de dados algébricos
Os novos tipos ajudam a dar expressividade ao código e checagem em tempo de compilação
type
type nome = definição do tipo
Ex.: type Produto = (Integer, String, Double)
Cria um apelido para tipo, na compilação será feita a substituição desse type definido pela definição de tipo.
Não permite tipos recursivos
Tipo Soma
data nome = op1 | op2 | .. | opn
Formado pela união de n valores (ou)
Palavra-chave: deriving -> cria instancias de tipos automaticamente
Existem n possibilidades para esse tipo
Tipo produto
data nome = construtor op1 op2 .. opn
Construtor é um 'envelope' para falar que as opções passadas fazem são do tipo ponto
Ex.: data Ponto = MkPonto Double Double
Ex.de uso: dist (MkPonto x y) (MkPonto x' y')
Tipo produto e tipo soma podem se misturar
Tipo parametrizados
Existe também tipos paramétricos. Define-se a existência de um elemento, porém fica em aberto qual é o tipo do elemento
Ex.: data Ponto a = MkPonto a a
Tipo Maybe, utilizado quando a computação pode falhar
Tipo Either, utilizado quando uma função gera dois tipos. Diz qual é o tipo de retorno através do 'Left' ou 'Right'
Ex.: Either String Int
Tipo recursivo
data nome = nome
Ex.: data Tree a = Leaf a | Node (Tree a) a (Tree a)
Tipo exponencial
Ex.: data Funcao a b = F (a -> b)
Esse função admite b^a possibilidades
Case of
Capturar padrões da execução da função
Ex.: case funcao parametro1 parametroN of
tipo1 -> ação
tipo2 -> ação
Record Type
Define-se o tipo e função de recuperação ao mesmo tempo
Ex.: data Ponto2D = Ponto { coordX :: Double
, coordY :: Double}
Classes de tipos
Classes defines grupos de tipos que precisam conter certas funções
Ex.: classe Eq, precisa das funções (==) e (/=) sendo o mínimo necessário uma delas
|
45 |
LUCAS ZOCCHIO |
A construção de tipos permite especificar tipos de dados diferentes daqueles já implementados no Haskell.
Com isso é possível restrigir valores passados e recebidos por funções de acordo com a aplicação desejada.
Há três formas de construir novos tipos:
- com "type" cria-se um apelido para o tipo, que será substituídoem tempo de compilação pelo tipo definido.
Dessa forma o novo tipo apresenta um bom desempenho, mas não funciona simplesmente como um apelido,
não permitindo distinguir tipos com assinatura igual.
- com "data" cria-se um novo tipo de dado e as funções que possuem esse tipo na assinatura possuem a restrição de
somente poderem receber ou retornar um valor daquele tipo específico, independente da assinatura do tipo.
Com isso é possível criar tipos soma, tipos produto, tipos exponenciais e tipos recursivos, pois o "data"
aceita vários construtores.
- com "newtype" cria-se um novo tipo que não é como o apelido no caso "type", mas pode ser substituído em tempo
de compilação, diferente do "data". Entretanto somente aceita um construtor.
Usando o "data", é possível utilizar o RecordType, onde se define nomes a funções que podem retornar os
parâmetros de um valor daquele tipo.
Esses tipos de dados são chamados algébricos (ADTs), pois apresentam leis similares às da álgebra comum, como soma e multilpicação.
É possível construir algo similar à derivada também com um ADT. Essa estrutura se chama Zipper e permite, por exemplo,
caminhar para frente e para trás numa estrutura como a lista ou uma árvore binária.
|
56 |
LUCCA IANAGUIVARA KISANUCKI |
Criando novos Types em Haskell, usando 'type'
type Produto = (Integer, String, Double)
Criar um dicionário:
type Assoc k v = [(k,v)]
find :: Eq k => k -> Assoc k v -> v
find k t = head [v | (k',v) <- t, k == k']
Tipo Soma:
Todos começar com caracter maiusculo
data Dir = Norte | Sul | Leste | Oeste
deriving Show
Tipo Produto:
data Ponto = MkPonto Double Double
MkPonto - Nome para identificar um construtor de dois valores double
Tipos Parametrizados:
Para deixar o tipo em aberto
data Identidade a = Id a
data Maybe a = Nothing | Just a
Tipo Recursivo:
Um tipo que usa ele mesmo
data Tree a = Leaf a | Node (Tree a) a (Tree a)
Record Type:
Um jeito diferente de tipo produto
data Ponto3D = Ponto { coordX :: Double , coordY :: Double}
Tipos de Dados Algébricos:
Either: soma de Tipos
data Either a b = Left a | Right b
Pair: operação de produto
data Pair a b = (a, b)
Zippers
Com o Zippers podemos andar livremente para frente e para tras em uma lista
data Zipper a = Z [a] [a]
walkRight, walkLeft :: Zipper a -> Zipper a
walkRight (Z lft (x:rgt)) = Z (x:lft) rgt
walkLeft (Z (x:lft) rgt) = Z lft (x:rgt)
Classes de Tipo:
Com a palavra 'class' podemos definir uma nova classe de tipos
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
'instance' para declarar uma nova instancia de uma classe
instance Eq Bool where
False == False = True
True == True = True
_ == _ = False
Info:
No GHCI o comando ':info' mostra as informações sobre os tipos e classes |
57 |
LUIZ FELIPE LEAL GOMES AZZOLINI |
|
59 |
MARCELO CECILIO FAGUNDES DA SILVA FILHO |
No haskell é possível a criação de outros, para fazer isso há 3 opções.
Type: permite criar um apelido para um outro tipo. Um exemplo é o tipo String que nada mais é do que [Char]. O type não permite que o tipo seja especificado como ele mesmo. Além disso por ser apenas um apelido o haskell o entende como o tipo anterior, por isso é possível usar String ou [Char] sem qualquer problema. A vantagem é que o type é rápido de ser compilado.
Data: diferente do type é criado um tipo diferente que não pode ser substituído pelo tipo anterior, sem conversão. A desvantagem é que data é mais custoso do que o type.
Newtype: seria uma opção de meio termo. Ele cria um novo tipo, porém só até o algoritmo ser compilado, depois ele é tratado como um sinônimo. Porém newtype não permite algumas operações que data permite.
Os novos tipos possíveis são separados em categorias:
Soma: a quantidade de representações são a soma dos tipos. Nele se define os valores possíveis, exemplo Bool = True | False que possui duas possibilidades.
Produto: a quantidade de representações é o produto das representações de cada tipo. É necessário um construtor para gera-los, exemplo um tipo Ponto = (MkPonto, Double, Double), MkPonto é o construtor e os Doubles as coordenadas.
Recursivo: são tipos que chamam a si mesmos. Como exemplo uma árvore binária Tree a = Node (Tree a) a (Tree a), onde um nó que chama dois outros tipos Tree e assim por diante.
É possível misturar os tipos exemplo Tree a = Leaf a | Node (Tree a) a (Tree a).
É possível também criar classes que são o conjunto de vários tipos que obedecem a determinadas propriedades. Exemplo a classe Integral, que representa todos os tipos inteiros, e suas possíveis operações.
|
60 |
MARCELO MARTINS OLIVEIRA |
|
69 |
MARIANA MIWA OKUMA MIYASHIRO |
Tipos de Dados Algébricos
1. Criando novos Tipos
- assinatura não é clara o suficiente
- em Haskell: criar tipo, ex: type Produto = (Integer, String, Double)
- type cria um "apelido" para um certo tipo (ex: type String = [Char])
- tipos paramétricos: type Assoc k v = [(k, v)]
2. Tipos de dados Algébricos
- Tipo Soma: união de diferentes valores
- data Bool = True | False
- Tipo Produto: cria encapsulamento
- data Forma = Circulo Ponto Double
| Retangulo Ponto Double Double
- Tipo parametrizado
- data Maybe a = Nothing | Just a
- trata erros e exceções (ex: função divisão retorna Maybe Int)
- capturar erros com case:
case (maybeDiv m n) of
Nothing -> error "divisão por 0"
Just x -> x
- Either: permite que função retorne dois tipos diferentes
- Terceira forma de criar novo tipo:
- newType Nat = N Int
3. Tipos Recursivos: usa a própria de definição na sua definição
- árvore binária: data Tree a = Leaf a | Node (Tree a) a (Tree a)
- outra forma de produto: Record Type
4. Álgebra dos tipos: similar com álgebra matemática
- possível definir funções absurdo, que retorna inteiro ao receber () ou que recebe valor e não retorna nada
- data Bool = False | True equivale a type Bool = Either () ()
- Either define soma de dois tipos
- Pair define produto de dois tipos
- tipo da função restringe implementações (tipos paramétricos a tornam mais restrita)
5. Zipper
- type DiffList a = Pair (List a) (List a) (pois derivada de lista são duas listas)
- uso em estruturas atravessáveis (listas, árvores)
- torna possível percorrer listas em tempo constante (frente/tras)
6. Classes de tipo: grupos
- palavra reservada Class
- ex: class Eq a where ...
- instancia: instance Eq Bool where ...
- apenas tipos data e newtype podem ser instâncias
- Classes:
- Eq: igualdade
- Ord: ordem
- Show: imprimíveis
- Read: legíveis
- Num: numérica
- Integral: números inteiros
- Fractional: racionais
- Floating: ponto flutuante
- :info (comando); mostra informação de tipos e classes de tipo |
61 |
MATHEUS ALEXANDRE DE SENA |
|
63 |
MIGUEL MIRA FONSECA |
Podemos criar tipos de dados compostos utilizando a palavra-chave “type” que permite
atribuir um significado semântico a um tipo, funcionando como uma alias. Podemos ter
também tipo de dados algébricos que permitem criar novos tipos com a palavra-chave
“data”. O tipo soma que permite uma união de valores, por exemplo tipo Bool. Já o
tipo produto permite criar um tipo com um construtor que atua como envelope para
seus parâmetros. Os tipos parametrizados, por exemplo o tipo Identidade, Maybe e
Either. Há também a palavra-chave “newtype” que é uma alternativa segura ao “type”,
porém ele permite apenas um único construtor, diferente de “data” que permite mais de um.
Tipos recursivos, que são aqueles que são definidos pelo próprio tipo, com exemplo,
o tipo List e Tree. Temos também dois tipos especiais, o tipo Void e o tipo Unit que
permitem recriar operações algébricas para tipos. E uma função que mapeia a para b
também permite criar um tipo, que é o tipo exponencial, com b elevado a definições
diferentes possíveis. Desde que a e b tenha tipo definidos, caso contrário estamos
trabalhando com polimorfismo paramétrico, onde “class constraint” permite restringir
a quantidade de implementações possíveis.
Podemos usar a estrutura “zippers” para tornar as operações em álgebra de tipos
menos custosa, facilitando percorrer estruturas lineares e não-lineares de forma
mais facilitada. Por fim temos as classes de tipo especificam tipos com operações
automáticas associados, como a classe Eq e a classe Ord, que podem ser instanciadas,
isso é, permitem definir os métodos de uma classe par um dado tipo. |
64 |
MURILO GUIMARÃES BALLE |
|
67 |
NATALIA LEITE VARES DE SOUZA |
CRIANDO NOVOS TIPOS
Utilizando a palavra-chave ‘type’ podemos criar um novo tipo de dado, porém cria apenas um apelido para um certo tipo ou combinação de tipos já existentes.
TIPOS DE DADOS ALGÉBRICOS
São tipos completamente novos, que podem conter tipos primitivos. A partir da palavra-chave ‘data’
É possível utilizar também a função ‘newtype’, que define um novo tipo até ser compilado, depois ele é substituído como um sinônimo. Diferentemente da função ‘type’, que é um sinônimo.
TIPOS RECURSIVOS
Um bom exemplo para o tipo recursivo é a árvore binária, onde a tem algumas possibilidades, isto é, pode ser um nó folha, um nó com uma árvore à direita ou um nó com uma árvore à esquerda.
ÁLGEBRA DOS TIPOS
Os Tipos de Dados Algébricos apresentam algumas similaridades com a Álgebra matemática
É possível construir elementos algébricos utilizando ADTs, como por exemplo Zero e Um (conforme implementações vistas em aula).
ZIPPERS
No geral fazemos conversão de árvores para Zippers, uma vez que assim podemos criar uma separação da árvore em direita e esquerda, por exemplo
CLASSES DE TIPO
Para criar uma nova classe de tipos usamos a palavra-chave ‘class’
• Instâncias da classe: utilizamos a palavra-chave ‘instance’. Apenas tipos definidos por ‘data’ e ‘newtype’ podem ser instâncias de uma classe, portanto ‘type’ não é possível.
Temos alguns tipos de classes pré-estabelecidas:
• Eq: classe de igualdade (igualdade e desigualdade)
• Ord: classe de ordem (maior e menor)
• Show: classe imprimível
• Read: classe legível (extrai conteúdo de strings)
• Num: classe numérica
• Integral: classe de números inteiros
• Fractional: classe de números fracionais
• Floating: classe de pontos flutuantes
Derivação de instâncias: o Haskell consegue inferir muitas vezes as instâncias das classes mais comuns, assim só precisamos utilizar a palavra-chave ‘deriving’ ao definir um novo tipo.
|
66 |
NATALIA REGINA COSTANZI |
|
65 |
NATHALIA CORREA DOS SANTOS |
Na semana 4 estudamos Tipos de Dados Algébricos. Os TDA são bastante úteis para facilitar o entendimento dos códigos desenvolvidos, por exemplo, pode
haver a necessidade de diferenciarmos dois argumentos que possuem a mesma assinatura, nesse caso podemos utilizar de tipos para facilitar o entendimento
e leitura do código desenvolvido.
Os tipos de dados algébricos são tipos completamente novos, definidos pelo próprio desenvolvedor, esses podendo conter tipos primitivos, permitir expressividade
e permitir a checagem do código em tempo de compilação. Os TDAs podem ser de tipo soma, onde definimos quais valores o tipo pode assumir. Do tipo Produto, onde o tipo
encapsula outros tipos, nesse tipo também podemos ter o uso de um construtor (ou envelope), que é a declaração implícita para esse tipo. Também podemos criar um
novo tipo a partir da função NewType, porém essa função permite apenas um construtor. O newtype se diferencia do Type pois o type é apenas um sinônimo para tipos
pré existentes, enquanto o newtype define um tipo totalmente novo. Já a diferenciação do newtype para o data é que o newtype define o novo tipo até a compilação,
após a compilação faz uso de sinônimos.
Outras maneiras de definirmos tipos é utilizando de recursão, como no caso da árvore binária, ou utilizando Record Type.
Os tipos algébricos apresentam similaridades com a álgebra matemática, e podemos usar definições de Tipo Soma e Tipo Produto para remeter a essas operações algébricas.
Além disso também podemos implementar classes para os tipos de dados algébricos. Nesse tipo de paradigma a classe de tipos é um conjunto, ou uma coleção de tipos, o
que difere do conceito de classes que vemos em orientação a objetos. Quando dizemos que um tipo pertence a uma classe é o mesmo que dizer que ele está dentro
do conjunto de classes. |
73 |
PAULO GABRIEL MASSA |
|
70 |
PAULO HENRIQUE EIJI HAYASHIDA |
Utilizando a palavra chave Type pode-se apelidar uma assinatura de uma função, facilitando a compreesão das funções
A palavra reservada data indica nova criação de tipo, deriving Show permite a impressão dos valores do novo tipo no ghci, os valores dos tipos precisam começar com letra maiuscula.
Tipo Soma indica que a quantidade de valores que o tipo possui é igual a soma de todos os valores possiveis
Tipo Produto a quantidade de valores representados é igual ao produto dos valores possiveis.
Tipo parametrizados são tipos que recebem variavéis do tipo a, sem tipo definido, podendo possuir qualquer valor como Int, Float, Double, Char, String.
Maybe é um tipo que armazena Nothing(nada) ou apenas uma variavel de um tipo
Either armazena dois tipos diferentes, podendo ser acessadas por Left e Right. Nesse caso a ordem de declaração desse tipo é muito relevante.
Tipo Recursivo é um tipo que a definição é feita de forma recursiva, ou seja o proprio tipo é chamado durante a construção dele mesmo.
Record Type define funções para nomes de campos, auxiliando na vizualização dos tipos e permitindo chamar um dos tipos que formam o tipo criado.
Either e Pair definem operações algebricas entre dois tipos, soma e produto respectivamente, onde o resultado das operações são a quantidade dos possiveis valores que o tipo pode assumir.
|
72 |
PEDRO ANTUNES NEGRÃO |
Na quarta semana foi apresentado os tipos de dados algébricos, abordando desde a criação de novos tipos de dados, definição de ADT, Zippers e classes de tipos.
Começando pela criação de Tipos, podemos utilizar o "type" para criar um apelido para um tipo, ou seja, o compilador apenas substitui a chamada do tipo pela definição que foi previamente descrita (i.e. type Pessoa = (String, Integer)). Para que realmente possamos criar novos tipos, existe a palavra reservada "data" e "newtype". Esse último é como um meio termo entre "type" e "data", pois ele além de apresentar apenas um construtor, ele também define um tipo (diferente do type) até ser compilado (diferente do data) e depois é substituído por um sinônimo.
Agora falando sobre os "tipos de tipos", existem 4 tipos:
* Soma: Não apresenta construtor e define valores únicos que esse tipo pode assumir. (i.e. data TipoTriangulo = Equilatero | Isosceles | Escaleno);
* Produto: Apresenta construtor, que nada mais é do que uma declaração implícita de uma função usada para criar um valor desse tipo, e também os tipos no qual será encapsulado (i.e. data Ponto = MkPonto Double Double);
* Recursivo: Como o próprio nome já diz, é um tipo que chama ele próprio em sua definição;
* Exponencial: Apresenta uma função dentro de sua definição.
Esses tipos apresentam esses nomes algébricos pois eles se referem à operações matemáticas para definir os valores possíveis de cada Tipo. Em um tipo Soma (Either) realiza-se a soma (Bool + Bool = 2 possíveis valores), no tipo Produto (Pair) aplica-se a multiplicação e assim por diante.
Por fim, o Zipper é um tipo de estrutura que permite percorrer uma lista ligada nas duas direções, porque antes de aprendermos essa estrutura, não tínhamos a referencia do elemento anterior na lista (porque é uma lista ligada). Fora isso, também aprendemos a criar classes de tipos (coleção de tipos). |
71 |
PEDRO MACHADO NERY DOS SANTOS |
Tipos de dados algébricos são a estrutura que permite criar novos tipos em Haskell. O comando type ajuda a criar apelidos que tornam tipos compostos mais significativos semanticamente no código. Podemos realizar agrupamentos de tipos com class constraints para definir associações, por exemplo.
Tipos soma permitem a união de valores dentro de um tipo. Tipos produto permitem especificar um tipo a partir de um construtor e outros tipos (é assim chamado pois pode representar a combinação de seus subtipos). Tipos paramétricos são utilizações parametrizadas dos tipos anteriores que permitem tratar casos específicos.
O tipo Maybe é um padrão utilizado para tratamento de casos em que não se necessariamente haverá retorno podendo ser acompanhado da estrutura case e error.
Ao criar um novo tipo, o comando data permite a checagem pelo compilador, dificultando erros de lógica relacionados ainda permitido por apelidos.
O comando newtype cria um novo tipo também tem essa característica, mas permite apenas um único construtor (limita tipos soma) e depois de compilado se torna apenas um apelido.
Tipos recursivos são tipos definidos em termos de si mesmos.
Record Types é uma sintaxe que permite criar funções auxiliares para recuperar informações de tipos.
A existência de inversos e elementos neutros garante flexibilidade na refatoração de tipos complexos.
Por fim, o tipo chamado exponencial é relativo a funções e outras estruturas que permitem diferentes resultados tanto a partir da definição da função quanto de seus parâmetros.
A álgebra de tipos pode ser utilizada para construção da estrutura Zipper. Essa estrutura permite focar em um item de uma estrutura e alternar para sua vizinhança de maneira eficiente.
Classes de tipo são grupos de tipos que devem conter um conjunto de funções especificadas. Podem ser criadas pelo comando class e Instâncias desse tipo podem ser definidas pelo comando instance.
|
75 |
PIETRO DI CONSOLO GREGORIO |
Em Haskell é possível definir novos tipos para simplificar e facilitar a leitura de funções. A palavra-chave type cria um apelido para um tipo e também torna possível a criação de tipos paramétricos (tipos com uma ou mais variáveis de tipo em aberto).
Além disso, através dos tipos de dados algébricos é possível criar tipos completamente novos que podem conter tipos primitivos e permitem checagem em tempo de compilação. Tipos soma são tipos onde a quantidade de valores que podem ser assumidos são dados pelas soma dos valores, por exemplo um Bool teria a soma 2 já que pode assumir apenas True ou False. Os tipos produto possuem um construtor para encapsular os n tipos, onde n é quantidade de tipos encapsulados. A sintaxe Record Type torna possível criar ao mesmo tempo funções que retornam cada valor daquele campo.
A função new type é uma outra forma de criar um novo tipo, ele cria um novo tipo e não apenas um sinônimo como é feito com o comando type, além de ser também substituído como um sinônimo após a compilação.
Os tipos recursivos são tipos em que na sua definição ele se refere à ele mesmo, como por exemplo na criação de uma árvore. Além disso é possível criar um tipo que não contém valor algum (Void) e um que possui apenas um único valor (unit). O tipo Either representa a soma dos tipos e o tipo Pair representa o produto dos tipos. Um tipo exponencial possui um número exponencial de combinações.
Em Haskell tempos o tipo como uma coleção de valores relacionados, a classe como uma coleção de tipos que dão suporte a certas funções ou operadores, métodos como funções requisitos de uma classe e instância definida como um tipo que pertence a uma determinada classe. |
76 |
PIETRO RISCHI NUNES |
|
12 |
RAFAEL BRUNO FERREIRA FIGUEIREDO |
Tipos podem ter "apelidos" para facilitar visualização de atributos:
type Produto = (Integer, String, Double)
type Cliente = (Integer, String, Double)
Esses tipos podem ser utilizados nas assinaturas de função para delimitar os tipos utilizados pelas funções. O type nao permite criação de tipo recursivo, como um nó de arvore que aponta para outro nó do mesmo tipo. Como são apenas apelidos nao ocupam espaço na memoria e é substituido em compilação.
Além disso podem ser criados tipos novos com o comando data. O primeiro caractere deve ser maiúsculos. São tipos novos e são criados e tem mais segurança em relação ao type, pois nao permite substituição entre tipos equivalentes. Maior custo Computacional. Os possiveis tipos sao:
Tipo Soma:
data Dir = Norte | Sul | Leste | Oeste -- tipo que cria uma direção
deriving Show -- cria a possibilidade de printar os valores
type Coord = (Float, Float)
type Passo = Coord -> Coord
para :: Dir -> Passo
para Norte (x,y) = (x, y+1)
Para Sul (x,y) = (x, y-1)
caminhar :: [Dir] -> Passo
caminhar [] coord = coord
caminhar (d:ds) coord = caminhar ds (para d coord) -- Isso fica igual um foldl!
caminhar ds coord = foldl (flip para) coord ds
Tipo Produto:
Tem a ver com a quantidade de valores que podem ser representados pelo tipo, neste caso double x double.
data Ponto = MkPonto Double Double -- MkPonto é um envelope/construtor do tipo que poderiar chamar Ponto
deriving Show
Tipos Parametrizados:
data Ponto a = MkPonto a a -- Os tipos sao adaptáveis!
-- data Maybe a = Nothing | Just a --tipo que pode ser utilizado quando a computação pode falhar, retornando nothing que pode ser tratado.
divComErro :: Int -> Int -> Int
divcomErro m n =
case maybeDiv m n of
Nothing -> error $ show m ++ " dividido por " ++ show n ++ " não existe!"
Just x -> x
-- data Either a b = Left a | Right b -- Ele gera um valo do tipo a ou do tipo b.
eitherDiv :: Int -> int -> Either String Int
eitherDiv x 0 = Left "Divisao por 0"
eitherDiv x y = right (x `div` n)
newtype: Ele cria a segurança do data entretanto não cria um tipo novo, usando menos memória e com menor custo computacional. As limitações estão na forma da construção.
Tipo recursivo:
usando o comando data é possivel crair tipos que contem os proprios tipos. O melhor exemplo sao arvores onde os nós contém nós:
data Tree a = leaf a | Noce (Tree a) a (Tree a)
Record type:
Sao embutidos na declaração do tipo e são criados na forma de funções. Por convenção usa _ para diferenciar.
data Ponto3D = Ponto {_coordX :: Double}
{_coordY :: Double}
{_coordZ :: Double} deriving Show
Algebra de dados:
Um tipo soma e um tipo produto do mesmo tamanho podem ser transformados.
Tipo exponencial:
O crescimento do tamanaho possivel das funções cresce exponencialmente com os tipos utilizados.
Polimorfismo:
Quanto mais aberta a assinatura mais restrito o funcionamento da função.
Classe de tipo:
Cria regras que permite organizar os tipos. Ex: Ordenação, igualdade, etc |
77 |
RAFAEL PAUWELS DE MACEDO |
O primeiro assunto dentro do tema de tipos de dados algébricos foi sobre podemos criar apelidos de tipos usando a palavra reservada type, como por exemplo type Produto = (Integer, String, Double). Porém só a criação do apelido não garante que os tipos de uma função vão ser garantidas, uma vez que dois tipos podem ser apelido da mesma estrutura.
Logo depois estudamos a criação de tipos de dados algébricos, que são mais que apelidos. Temos tipo soma, tipos produto, parametrizados, recursivos e exponenciais. Para todos os tipos usamos a palavra reservada data, por exemplo um tipo soma é definido como data Dir = Norte | Sul | Leste | Oeste
Além do type e do data temos também o newtype, que mantém a segurança da compilação que temos no data e não adiciona nenhum overhead como o data faz, sendo a única limitação o fato de newtype não suportar múltiplos tipos no construtor.
Existe também os chamados Record Type que facilitam o acesso aos valores de cada argumento usado na construção de um tipo, por exemplo, o record type data Ponto = Ponto { _x :: Double, _y :: Double } disponibiliza os nomes de campo _x e _y como funções que recebem Ponto e devolvem o valor do campo. A convenção destas funções é usar o _ no início do nome.
Dentro da seção de álgebra de tipos vimos os tipos Void e (), que podem ser úteis para aumentar a segurança do nosso código e como podemos representar as funções de forma algébrica, provando que as propriedades da álgebra também são aplicáveis dentro do mundo das funções, depois das provas entramos na definição algébrica de uma lista.
Por fim temos as classes de tipo que usam a palavra reservada class, por exemplo,
class Eq where (==), (/=)... |
78 |
RAPHAEL RAMOS DA SILVA |
Novos tipos de dados
Em Haskell, podemos criar um novo tipo de dados utilizando a palavra-chave type, que cria um apelido a um certo tipo.
Exemplo: type Strinng = [Char]
Exemplo: type Coordenadas3D = (Int, Int, Int)
Tipos de Dados Algébricos: Utiliza a palavra-chave data, que permite a criação de novos tipos de dados (inclusive recursivos) com checagem em tempo de compilação:
- Tipo soma: lista de valores/nomes determinados.
Estrutura: data <nome_do_tipo> = valor1 | valor2 | ... | valorn
Exemplo: data Pessoa = Física | Jurídica
- Tipo produto: encapsulamento de valores (indetermoinados no momento da criação do tipo).
Estrutura: data <nome_do_tipo> = <construtor> Tipo1 Tipo2 .... Tipon.
* O construtor representa a função que deve ser chamada para contruit um novo valor deste tipo.
** Os Tipos1...n são os tipos encapsulados pelo construtor.
*** Também é possivel definir esse tipo utilizando Record Type
Exemplo: data Ponto2D = ConstroiPonto Double Double.
Uma terceira forma de criar um novo tipo é com a palavra-chave newtype (apenas um construtor)
Exemplo: newtype Natural = Nmaker Int
|
49 |
RENAN FERREIRA LIMA |
No Haskell é possível utilizar o type para criar apelidos de tipos e assim utilizar estes nas assinaturas de funções. Contudo, como se trata de um apelido não é permitida a criação de tipos recursivos, isto é, criar um type que contenha ele mesmo nos argumentos, nessa situação é necessário utilizar uma outra forma de se criar o tipo. Uma característica importante do type é que não demanda espaço de memória adicional, nem tem um custo computacional extra, uma vez que trabalha com apelidos.
Uma outra maneira de se definir tipos é usando o data que, diferentemente do type, não tabalha com apelidos, criando de fato um tipo novo. Isso gera uma segurança extra pois impõe mais barreiras na compilação, inviabilizando o uso equívocado de um tipo data, por outro lado requer um custo computacional. Trabalhando com data, é possível utilizar tipos paramétricos como: Identidade, Maybe, Either, entre outros. Com esse artíficio, é possível implementar avisos de erros nas entradas, trabalhar com tipos recursivos e empregar a álgebra de tipos.
Quanto a álgebra de tipos é possível fazer a composição de tipos, por exemplo, realizar a soma de dois tipos e analisar o retorno de modo similar à álgebra convencional. Isso garante flexibilidade para refatorar os tipos e facilitar a construção de implementações com tipos mais complexos. O Haskell restringe o escopo da função através da assinatura definida, sendo este outro ponto de segurança da implementação.
Um exemplo de aplicação da álgebra de tipos é a estrutura Zipper que facilita a implementação de uma lista encadeada. Há ainda a Classe de tipos que define grupos de tipos que tenham certas funções de grupos especificadas. |
79 |
RENAN GONCALVES MIRANDA |
Criando novos tipos
Através dos tipos de dados algébricos é possível criar novos tipos de dados. Quando é passado uma assinatura de função, não é possível descobrir quais os elementos de entradas sem ver a função. Quando criamos um apelido para o tipo (em haskell utilizamos o type), podemos identificar melhor as entradas de cada assinatura da função. O type não permite a criação de tipos recursivos.
Tipos de dados algébricos
Tipos algébricos permite a criação (a partir da função data do haskell) de tipos novos através de tipos primitivos. Eles tem uma certa similaridade as operações algébricas da matemática que conhecemos.
O tipo soma é um tipo formado pela união de diferentes valores.
O tipo produto é um tipo que presenta a quantidade de valores que podemos representar pelo tipo.
Nos tipos parametrizados é passado o parâmetro do tipo a ser recebido.
O tipo Maybe é utilizado quando a programação pode falhar (exemplo, uma divisão por zero)
O tipo Either pode retornar à função valores diferentes.
Também podemos criar um novo tipo usando o newtype, que permite apenas um construtor.
Os tipos recursivos são definidos utilizando o próprio tipo que estamos definindo (exemplo é a lista e árvores).
O tipo exponencial é uma tipo função (data Funcao a b = F (a -> b)). Admitindo b elevado à a valores.
Zippers
É uma função que permite caminhar para ambas direções de uma lista.
Classes de Tipos
As classes de tipos define grupos de tipos que tem que conter certas funções especificadas (por exemplo a classe Eq que contem os tipos de igualdade e desigualdade).
Uma classe nada mais é que uma coleção de tipos, um método é uma função de uma classe e instância é a definição dos métodos de uma classe para um tipo. |
84 |
RENATO VINICIUS TURTIENSKI POSSA |
|
82 |
SAMUEL ESDRAS NAVARRO DA SILVA |
|
83 |
TAMIRES CHRISTYNE DA SILVA |
|
86 |
VICTOR LOURENCO BORGES |
** Tipos (apelidos) **
- permitem agrupar dados de forma mais semântica, e usar o tipo em argumentos. É um apelido que o haskell irá substituir pelos valores
- type Produto = (Integer, String, Double)
- preco :: Produto -> Double
- preco (_, _, preco) -> preco
- podem trabalhar com tipos genéricos: type Assoc k v = [(k,v)]
** Tipo Soma **
- contém um dos valores informados (enum)
- data Enum = Nome1 | Nome2 | Nome3
- deriving: adiciona propriedades ao novo tipo (show para imprimir)
** Tipo Produto **
- pode conter mais de um tipo de valor (data class)
- data Ponto = MkPonto Double Double, onde MkPonto é o nome do construtor do tipo
- como argumento: (MkPonto x y)
- é possível combinar os dois tipos: data Forma = Circulo Ponto | Retangulo Ponto Ponto, onde Circulo e Retangulo são os construtores do tipo (assim como o MkPonto)
- pode receber tipos genéricos: data Id a = Id a
- o data pode ser substituído por newtype, que é mais performático, mas não possibilita mais de um construtor
** Maybe **
- data Maybe = Nothing | Just a
- se a função falhar (div por 0), retorna Nothing. Se bem suceder, retornar Just com o resultado
** Either **
- data Either a b = Left a | Right b
- ou retorna o lado esquerdo (a) ou lado direito (b)
- por exemplo, se a função falhar, pode retornar um Left "Deu erro", se funcionar Right True
** Tipo Recursivo **
- permite recursão do próprio tipo
- data Arvore a = Folha a | No (Arvore a) a (Arvore a)
** Tipo Record **
- cria funções para cada um dos atributos
- data Ponto3d = Ponto { _X :: Double, _Y :: Double, _Z :: Double }
- pode ser usado com os outros tipos
** Zipper **
- quando percorremos uma lista, perdemos a referência dos elementos que já passaram
- com o zipper, ao avançar um elemento na lista, guardamos numa segunda lista, em ordem reversa, os elementos já percorridos
- o mesmo pode ser feito com árvores
** Classes de Tipo **
- é uma coleção de tipos, que possuem métodos dos quais podem ser usados por todos tipos daquela classe
- tipos novos podem derivar classes: deriving (Show, Read)
|
87 |
VINICIUS DE OLIVEIRA CAMPOS DOS REIS |
|
88 |
VINICIUS LOURENCO DA SILVA |
|
0 |
VITOR MARINI BLASELBAUER |
|
89 |
VITOR RUBENS SNIQUER LEAO MARTINS |
|
85 |
VITTORIA ARIEL DOS SANTOS BOROTTO |
=> Criando novos tipos em Haskell
A assinatura sem implementacao e argumentos, nao diz o que significa a funcao.
Podendo usar assinaturas diferentes em contextos errados.
Antes:
troco :: (Integer, String, Double) -> (Integer, String, Double) -> Double
Depois:
troco::Produto->Cliente->Double
=>Type(apelido)
type Produto=(Integer, String, Double)
o String é o apelido para um [Char]
=>Tipo Parametrico
type Assoc k v=[(k,v)]
os types nao permitem recursao de tipo
=>Tipos Algebricos
Maior expressividade, verificados em tempo de compilacao.
1.Tipo Soma
data Direcao = Norte | Sul | Leste | Oeste
deriving: permite que peça para o compilador criar instancias automaticamente
2.Tipo Produto
Podemos misturar os tipos soma e produto:
data Forma = MkCirculo Ponto Int | MkRetangulo Ponto Int
Mk:FUNCOES construtoras
=> Tipos Parametrizados: deixa mais generico
Permite que funcoes retornem valores de tipos diferentes
data Either a b = Left a | Right b
type vantagem:apelido,nao ocupa espaco computacional
data vantagem: seguro, por verificar a origem e tipos distintos
newtype: cria novo tipo igual data, mas nao causa o overhead
4. Tipo Recursivo
data Lista a = Vazia | Cons a (Lista a)
Algebra dos Tipos
O Zero é um tipo que não contém valor algum(Void)
O Um,unity unico valor possivel é ()
A soma de tipos funciona da mesma forma que funciona na algebra:
type ZeroMaisUm = Either Void () = ()
5. Tipo Exponencial
data Funcao a b = F (a -> b)
esse tipo possui:b^a valores, definicoes diferentes
=>Zipper(aplicacao da algebra de tipos, para otimizar operacoes)
Utilizando a lista como exemplo, só podemos andar para frente.
Esse tipo de estrutura é chamada de Zipper e tem benefícios com o uso de estruturas atravessáveis
=>Classe de tipos:define grupos de tipos que devem conter algumas funções especificadas
Instancias de classe: só data e newtype podem ser instâncias de alguma classe.
Metodos de classe: sao funcoes
|
90 |
WALTER OSCAR TRUJILO |
|
91 |
WESLEY AXEL DE BARROS |
Para esta semana 04, tivemos um topico importante para o estudo de Haskell na disciplina de Paradigmas de Programação.
Estudamos a criação de tipos que são tipos compotos de elementos em um código com a finalidade de melhor identificação e utilização no mesmo.
Com esses tipos, podemos criar diversos modelos diferentes, como tipos parametricos que possuem váriaveis, ou tipos recursivos. Utilizando construtores e outros tipos para encapsular
os valores.
Com o encapsulamento desses tipos de maneiras diferentes, conseguimos implementar algoritmos complexos de maneira mais fácil, como por exemplo a implementação de uma árvore binaria Utilizando
tipo recursivo.
Também é possivel utilizar os tipos para realizar operações de adição, multiplicação e exponenciação utilizando o principio dos tipos Zero e Um ().
Uma utilização interessante para os tipos é para a construção de Zippers, que por exemplo, com base em uma lista de elementos n, acabam divindo essa lista em duas permitindo assim percorre
livremente entre os elementos dela.
Verificamos qual a definição de classes em Haskell, que são um conjunto de tipos a serem utilizados e instanciados para serem utilizados em outras funções.
|
92 |
WESLEY BATISTA SOARES |
|
33 |
WILLIAM DE SOUZA GOMES |
Quando temos uma assinatura da função e não temos sua implementação não podemos dizer muito o que faz e também se eu não tenho nomes significativos nos argumentos, não fica muito fácil entender.
Para contornar tal problema, temos em Haskell a palavra chave type, ele cria um apelido para tipo.
Exemplo seria type PessoaInfo = (String, Double, Double), posso especificar qual nome para cada tipo na tupla da seguinte maneira
type PessoaInfo nome altura peso = (String, Double, Double)
Podemos criar tipos de dados novos que não são apenas apelidos
o tipo Bool é um exemplo que tem a seguinte implementação data Bool = false | true, ou seja, ele pode ser apenas um dos dois tipos.
Ao criarmos um tipo Direção como mostra abaixo
data Dir = Norte | Sul | Leste | Oeste
deriving Show
O deriving show estamos dizendo que podemos imprimir os valores desse tipo. Ele já transforma numa string.
Podemos criar também um tipo para a assinatura da função.
Temos também o tipo parametrizados como o Maybe que pode retornar Nothing ou Just, muito utilizado para tratamento de erros no programa.
Record type simplifica as definições dentro do tipo, então podemos já definir na ciração do tipo, como mostrado abaixo
data Ponto3D = Ponto { coordX :: Double
, coordY :: Double
, coordZ :: Double
}
Em algebra dos tipos temos o Pair que representa a multiplicação de dois elementos e o Either que seria a soma
Então para o exemplo seguinte (x+y)*z= (x*z) + (y*z) poderiamos escrever com o seguintes tipos
type Tipo1 x y z = Pair (Either x y) z
type Tipo2 x y z = Either (Pair x z) (Pair y z)
Com a estrutura Zipper é possível seguir na lista e manter o controle dos elementos que passaram, ou seja, é possível caminhar para frente ou para trás livremente. Podemos definir o zipper como um tipo a seguir
type Zipper = Z [] [] |
93 |
WILLIAM SENA SILVA |
|
94 |
WILLIAN CORTEZ |
|
21 |
francesquini |
|