Nome TextoResumo
1 ALLEF KRISTIAN TAVARES ROCHA
2 ANDRE RICCA YOSHIDA Applicative Functor: - É uma estrutura intermediária entre functores e mônadas. Os functores aplicativos permitem que os cálculos funcionais sejam sequenciados, mas não permitem o uso de resultados de cálculos anteriores na definição dos subsequentes. - Exemplo: > fmap2 (+) [1,2] [3,4] [4,5] > fmap2 (+) (Just 3) (Just 2) Just 5 Applicative: - Currying: - Dada uma função f do tipo f: (X x Y) → Z, a técnica de currying pode transformar a expressão em curry(f): → (Y → Z) Exemplo Applicative: - > pure (+) <*> [1,2] <*> [3,4] -- [4,6] > pure (+) <*> (Just 3) <*> (Just 2) Just 5 Applicative Maybe: - Exmeplo de definição: instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx Computação não-determinística: - Dada uma certa entrada, pode apresentar comportamentos diferentes em diferentes execuções, ao contrário de um algoritmo determinístico.
3 ANGELO MAEDA ROJAS Applicatives A classe de tipo Applicative é definida como class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b O significado de pure é a de que estamos transformando uma função pura em um determinado contexto computacional. Segue abaixo um exemplo para instância da classe applicative, no caso para o tipo de dado Maybe. instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx Com isso podemos utilizer expressões como - pure (+) <*> Maybe 3 <*> Maybe 4, Que tem como resultado Maybe 7. - pure (+) <*> Maybe 3 <*> Nothing, Que tem Nothing como resultado Traversable A classe do tipo traversable é definida como class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) Essa classe é útil quando, por exemplo, temos uma função que mapeia um tipo “a” para um tipo ”Maybe b”. Nesse caro querendo um Maybe [b] e não uma lista de Maybe. Dica: Um sequenceA aplicado após fmap é um traverse sequenceA :: (Applicative f) => [f a] -> f [a] sequenceA [] = pure [] sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs [BÔNUS] É possível, pois o tipo de dado Set só encapsula uma lista de tipo “a”, logo é possível instanciar utilizando-se a instância de Functor para listas. A instância do Functor para Set fica da seguinte forma: Instance Functor Set where Fmap f (Set a) = Set (map f a)
4 ANTONIO DUARTE CANTANHEDE NETO
7 BRUNA ISHIDA Com o Applicative Functors há a possibilidade de extender e possibilitar uma maior generalização de fmaps. O Applicative, resolve os casos de fmap por meio da utilização de currying, há a utilização de um padrão nomeado `pure` para nomear o método puro em um contexto determinado. Há a possibilidade de definir o tipo de Applicative como um Maybe, uma Lista ou um SafeNum. Transversable é um tipo de classe que possibilita o mapeamento de tipos. Ela é muito quando possuímos uma lista de valores do tipo x e gostaríamos de implementar um outro tipo para todos os elementos dessa lista ao invés de implementar o tipo apenas sobre a lista como um todo. Folds combinam métodos e estruturas de dados, ou seja, implementam o método para cada um desses dados que compõem a estrutura. Com o Applicative, há a possibilidade de resolver os casos de fmap para o tipo Fold e, assim, combinar folds e retirar métodos cada vez mais complexos e completos.
8 BRUNA MIRELLI XAVIER GONCALVES 1. Applicative Functors Generalização da fmap para funções com mais do que um argumento. 1.1 Applicative Automatização de aplicação de funções a valores de tipos diversos que são processados e retornados na forma de functors. O padrão formado pelo uso de currying na aplicação de pure leva o nome de Applicative, que tem a classe de tipo: class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Realiza a geração automática de fmap. 1.2 Applicative Maybe Aplicação de funções puras a argumentos passíveis de falha, de modo a controlar o comportamento em caso de erros. Podemos realizar a aplicação de função usando o tipo Maybe definida por uma instância como: instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx 1.3 Applicative List Aplicação de operador em combinações de elementos de listas, cujo funcionamento se dá como dito na instância: instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs, x <- xs] 1.4 Computação não-determinística Uso do Applicative para retornar todas as possibilidades de operação entre listas quando há argumentos de lista não determinísticos. 2. SafeNum + Applicative É possível criar uma instância de Applicative para SafeNum que simplifica e generaliza sua versão com Functors. 3. Traversable É possível combinar a classe Traversable com o Applicative List para, por exemplo, retornar Maybe [b] ao invés de [Maybe b]. 4. Folds Também podemos criar instância Applicative para um tipo Fold, e generalizar a forma de aplicação de funções sobre esse tipo.
9 BRUNO STORER FRANCO MARTINS Nessa semana nos questionamos sobre a necessidade de se realizar operações matématicas entre duas estruturas de mesmo tipo, como por exemplo uma soma entre listas elemento a elemento, ou soma de árvores ramo a ramo. Exemplo de operação desejada: fmap2 (+) [1,2] [3,4] Nesse caso o resultado precisaria ser [4,5]. Uma classe chamada Applicative pode nos ajudar com esse tipo de problema. Segue a classe: class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Com isso podemos definir <*> ao implementarmos uma instância de Applicative em listas de forma que 'pure (+) <*> [1,2] <*> [3,4] gere' o resultado [4,5] desejado. Como mostrado a seguir: instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs, x <- xs] No caso de listas pode ocorrer de cada lista ter uma quantidade de elementos diferentes. Quando queremos realizar operações especificamente elementos a elementos de forma pareada utilizamos uma operação que nomeamos em aula como ZipList. Por último, isso aprendemos sobre a classe Traversable que permite maperar um tipo A para B em uma lista de A's por exemplo. Definimos Traversable como: class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) instance Traversable [] where traverse g [] = pure [] traverse g (x:xs) = pure (:) <*> g x <*> traverse g xs
10 CAIO ARGENTINO DE OLIVEIRA
11 CAIO CESAR RAMALHO FOLLADOR
6 CAIO HENRIQUE DOS SANTOS RIBEIRO
49 DIOGO AKIO BALBONI MIYAKE Functor: A classe de tipo Functor nos fornece uma maneira de generalizar a aplicação de função para tipos arbitrários. EM Haskell pode ser chamada de fmap do tipo `fmap :: (a -> b) -> f a -> f b` e pode ser descrita como: me dê uma função que recebe um a e retorna um b e uma caixa com um a (ou vários deles) dentro dela e eu darei a você uma caixa com um b (ou vários deles) dentro A classe Functor abstrai a ideia de aplicação de função a um único argumento. Essa classe nos fornece uma maneira de combinar funções com tipos, elevando uma função de um nível de abstração para outro. Aplicative : Permite aplicar funções com mais argumentos Fmap 2, fmap3, 4 … assim consegue -se mais generalização. Algo parecido com uma calculadora polonesa : pure f (+) <*> Just 3 <*> Just 4 <*> Just 5 que ele faria um : (3+4+5) retornando um 12 Traversable: Permite que tipos possam ser mapeados.Essa classe é útil quando, por exemplo, temos uma função que mapeia um tipo a para Maybe b e temos uma lista de a. A classe de tipo Traversable se relaciona ao mapa da mesma maneira que Foldable se relaciona à dobra Folds: Folding é um conceito que se estende em utilidade e importância além das listas, mas as listas são muitas vezes como eles são introduzidos. Folds como um conceito geral são chamados catamorfismos. Catamorfismos são um meio de desconstruir dados. Se a espinha dorsal de uma lista é a estrutura de uma lista, então um fold é o que pode reduzir essa estrutura [BÔNUS] Não, pois só podemos criar instâncias de Functor de tipos que têm exatamente um parâmetro de tipo. Não podemos escrever uma implementação de fmap para E a b ou (a, b), por exemplo, porque eles têm dois parâmetros de tipo. Também não podemos escrever um para Bool ou Int, pois eles não têm parâmetros de tipo.[Real Life Haskell] No caso do Set ele não pode ser implementado devido a necessidade de ser Ordenado.
13 EDUARDO MACIEL DE SOUZA Nessa semana fomos apresentados aos Applicative Functors e Traversables. Em Applicatives abordamos os seus usos com Maybe e Listas. Com Maybe podemos realizar um encadeamento de operaçõs do tipo Maybe e termos segurança de que caso alguma dessas operações resulte em Nothing, receberemoso Nothing como resultado, não precisando tratar todas essas excessões para cada uma das aplicações da função. Para listas vimos que o operador <*> atua com uma lógica distributiva, realizando todas as combinações possíveis entre os elementos das listas. Vimos também que devido a essa propriedade com o tipo Maybe, Applicatives se tornam uma ótima ferramenta para trabalharmos com operações que podem conter excessões, pois assim não precisamos declarar a cada aplicação da função o comportamento esperado para o resultado Nothing. Além disso estudamos que os Transversables são capazes de receber uma estrutura e isolar delas um "fator comum", ou seja, podemos fazer o caminho inverso de uma distribuição. Um exemplo: [Just a, Just b, Just c, Just d] => Just [a, b, c, d]. Essa ferramenta aliada a Applicatives torna possíveis a aplicação e avaliação de excessões em Haskell.
14 EUGENIO VERAS MARIA Para não usar varios fmap podemos usar Applicative Teriamos pure e uma funcao f pure :: a -> f a f :: f(a -> b) -> f a -> fb Com isso podemos fazer: fmap2 g x y = f (f (pure g) x) y Temos uma classe que faz isso: class FUnctor f => Applicative f where pure : a -> f a (<*>) :: f (a -> b) -> f a -> f b A funcao f seria <*> Podemos instanciar esse classe: instance Applicative Maybe where pure x = Just x Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx Para usar podemos fazer: pure (*) <*> Just 5 <*> Just 9 Para casos não deterministicos as listas irao gerar todos resultados possíveis pure (*) [1,2,3] <*> [2,3] = [2,3,4,6,6,9] Traversable pode para a execução ao achar um valor vazio, ignorando todo o resto da lista
15 FABIO DOS SANTOS DE SOUZA
16 FELIPE PONSANO FRANKE
22 GABRIEL ALBANO SANTOS Applicative - No Haskell, por padrão, ao passarmos vários parâmetros para uma função, esta na verdade processa apenas um parâmetro e retorna uma função que processa o próximo parâmetro e assim por diante, apesar de parecer que a função processa todos os parâmetros de uma vez. Por isso, ao mapearmos funções em functors, usávamos funções que recebiam apenas um parâmetro. Mas com o uso do Applicative, podemos mapear funções como * e +, que recebem mais de um parâmetro, sobre functors. Applicative Functors são uma classe que dado um Functor F, é definida pela função pure (que gera um valor puro dentro do contexto) e um operador (aplica). Traversable - São Functors que representam estruturas de dados que podem ser nevegados da esquerda para a direita, performando uma ação sobre cada elemento. Ou seja, Traversable Functors são aqueles os quais possuem zero ou mais elementos, e um ordem atrelada à esses elementos, possibilitanto uma aplicação de função para cada um deles em ordem. Essa classe é útil quando, por exemplo, queremos retornar um Maybe [b] como retorno de uma função que mapeia um tipo a para Maybe b, ao invés de retornar um [Maybe b].
23 GABRIEL BELLOMI MEALE Applicative Uma família de funções de fmap pode ser mapeada com Applicative (fmap recursivo) No caso, o fmap zero poderia ser representado pelo pure: pure :: a -> b E uma generalização do fmap que seria o aplica: aplica :: f (a -> b) -> f a -> f b Dessa forma: fmap0 = pure fmap1 g x = aplica (pure g) x fmap2 g x y = aplica (aplica (pure g) x) y ... e assim por diante. A classe Applicative, portanto, pode ser definida como: class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Com uma instância de Applicative, agora podemos implementar coisas como: pure f <*> Just 3 <*> Just 2 <*> Just 5 pure (+) <*> [1,2] <*> [3,4] Traversable Conjunto de classes "atravessáveis" por todo o tipo de sequencias. class (Functor t, Foldable t) => Traversable where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) Exemplo: g :: a -> Maybe b [g x1, g x2, g x3] :: Maybe [b] Nesse caso, gostaríamos que o retorno fosse um Maybe [b] e não [Maybe b] A implementação com o Applicative poderia ser: pure (:) <*> g x1 <*> (pure (:) <*> g x2 <*> (pure (:) <*> g x3 <*> pure [])) :t sequenceA (implementado pela biblioteca Data.Traversable) sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) [BÔNUS] Um Set, em sua implementação, necessita que seu typeclass "a" seja "Ord", o que o impede de ser um Functor. Portanto, Set falha em satisfazer a lei: fmap f . fmap g = fmap (f . g)
17 GABRIEL DE MELLO FIALI Applicative - Classe que padroniza o método de currying, que permite generalizar fmaps, para receber mais elementos como parâmetros. - Conta com o método pure e o operador (<*>), podendo ser resumidos por <$>. - As instâncias para tipos específicos são feitas definindo pure e (<*>) para o mesmo. - Pode ser usado para aplicar operadores em combinações de elementos em listas ou tratar problemas específicos, como o caso de computação não-determinística; por exemplo. - Demonstração de seu uso com o tipo customizado SafeNum e cliffhanger de uma melhor alternativa de implementação para a próxima semana. Traversable - sequenceA: forma de realizar uma sequência de aplicações de uma determinada função. - Permite que as aplicações sejam interrompidas caso uma aplicação falhe, reduzindo o número de operações executadas, de acordo com o princípio da avaliação preguiçosa. - Útil para operações nas quais a ordem dos elementos é importante. - Traversable: Classe que permite mapear tipos específicos com estruturas percorríveis, além de modificá-las. - Exige a instância de uma classe Functor, além de Foldable, para estruturas como árvores, ao contrário de listas. - Conta com o método traverse, que se baseia no uso de pure e (<*>) para realizar aplicações. - Útil para tornar o código mais declarativo e conciso. - Demonstração de alguns exemplos de uso para outras estruturas além de listas, incluindo o tipo Fold criado anteriormente.
20 GABRIEL MENDONÇA FARIAS Applicative Functors, permitem uma maior generalização de uma função do tipo fmap, como por exemplo, uma função composta por valores de tipos a, b e c, e através de funções fa, fb retornar uma função fc. O applicative functor, resume a aplicação deste tipo de função através do currying. Definindo pure :: a → f a, e aplica :: f (a → b) → f a → f b, sendo assim, ao invés de ter sempre que declarar todas as funções e seus tipos, pode-se (após declarar fmap0 = pure) apenas declarar que a função fmap2 é fmap2 g x y = aplica (aplica (pure g ) x ) y, assim, a função fmap2 irá realizar a mesma tarefa de receber valores do tipo a e retornar na forma de uma função tipo b, ou quantas mais funções e tipos forem necessárias, utilizando a mesma lógica. Para o Applicative Maybe, como pure, se declara apenas o próprio valor pure x = Just x, caso a entrada seja apenas Nothing, se devolve Nothing e na presença de uma função no operador, pode realizar uma função fmap na saída. Também é possível utilizar o Applicative List, a fim de realizar uma determinada tarefa para todos os elementos entre duas listas de maneira combinada, neste caso, como pure é devolvida a própria lista. E como função, a lista resultante será obtida com o uso de um list comprehension e a função requerida para a combinação esperada. Transversable é uma maneira de imediatamente retornar um valor nothing, assim que um dos valores envolvidos e avaliados em ordem for nulo. [BÔNUS] Não, pois um functor, usa uma função tipo (a → b) → a → b, sem restrições para os tipos a e b, enquanto o set usa (Ord a, Ord b) => (a → b) → Set a → Set b, a obrigatoriedade do uso de Ord na formação do set, impede que uma instância functor seja criada para a instância set.
21 GABRIEL MURAKAMI ALVES Um Applicative é um tipo intermediário entre os Functores e as Mônadas. São basicamente Functores com alguma aplicação, como sugere o nome. Esse tipo é definido por uma função pura e uma sequência de aplicações utilizando <*>. As definições de um Applicative ajudam a driblar falhas, uma vez que ele pode ter um retorno sem propagação de erro. O que podemos ver na definição do Applicative Maybe. Uma implementação de grande utilidade é o Applicative para listas, que facilmente define como se a operação entre duas listas, seja soma, multiplicação, concatenação, entre outros. Podemos utilizar para realizar operações não- determinísticas, como a multiplicação entre uma lista e uma lista vazia. Para executar uma operação pareada temos a ZipList. Como aplicação dos Applicatives temos o tipo Traversable. Utilizado quando queremos mapear um tipo a para um b e temos uma lista de a's. Da mesma forma que tínhamos uma instância de Functor para um tipo fold, agora podemos definir um tipo Applicative para o mesmo. Definindo sua função pure para um Fold (\_ -> ()) (\_ -> o) e as aplicações de toMonoid e summarize utilizando o operador <*>.
19 GABRIEL ROSSETTO MIGLIORINI
46 GABRIEL SILVESTRE MANCINI
26 GEORGE HARRISON ROCHA • Applicative Functor - Applicative Functor ou simplesmente Applicative é uma estrutura que estende a capacidade do Functor com os operadores pure e <*>, permitindo uma maior generalização do fmap; - Em aula foi mostrado uma instância de Applicative para: - Maybe; - listas; - Fold; - SafeNum, estrutura implementada em aulas anteriores. • Traversable - sequenceA: função que avalia uma sequência em ordem e para de computar quando encontra uma falha; - Classe Traversable: classe que implementa todas as estruturas que podem ser atravessadas através de uma sequência; - Em aulas foi mostrado exemplos de instâncias de Traversable para: - listas; - Tree; - Fold. [BÔNUS] Não é possível implementar uma instância de Functor para o Set a porque não podemos implementar fmap :: (a -> b) -> f a -> f b, pois sem uma instância para Ord b não é possível construir f b de forma a garantir que o Set não tenha elementos duplicados.
27 GIANCARLO KAMI DELL ARINGA VIANA
54 GIOVANNA NOGUEIRA A classe (Functor) Applicative estende a capacidade do fmap, permitindo generalizá-la mais e utilizar mais argumentos. É definida pela função pure (que gera um valor puro de uma função dentro do contexto computacional) e um operador “aplica”. Criando uma instance de Applicative (no exemplo, para SafeNum), é preciso definirmos a forma pure e como funcionará o operador “aplica”. A classe Traversable implementa todas as estruturas que podem ser atravessadas através de uma sequência, que podem ser mapeados; implementando uma ação em cada um dos elementos. A xclasse base Functor significa que o recipiente não pode impor nenhuma restrição no tipo do elemento, logo, recipientes que necessitam que seus elementos sejam comparáveis, ordenáveis, etc., não podem ser instancias da classe Traversable
25 GIOVANNI ALMEIDA DE SOUSA Semana 6 - Paradigmas de Programação 1. Applicative (<*>): a. Definição: i. (<*>) :: Applicative f => f (a -> b) -> f a -> f b b. Exemplo: i. > a = Just (*2) ii. > b = Just 4 iii. > a <*> b iv. Just 8 c. Ao utilizar-se pure na função abaixo, estamos transformando uma função pura em uma função não determinística, isso é, que pode falhar. i. > pure (+) <*> (Just 3) <*> (Just 2) ii. Just 5 d. Applicative List (Applicative []): aplica um operador em todas as combinações entre duas listas. Exemplo: i. > pure (*) <*> [1,2] <*> [3,4] ii. [3,4,6,8] 2. SafeNum + Applicative: a. Definição: i. instance Applicative SafeNum where ii. pure = SafeNum iii. f <*> x = flatten $ fmap (`fmap` x) f 3. Traversable a. É uma função importante quando a sequência é relevante no algoritmo. Por exemplo, quando deseja-se parar a compilação assim que uma falha ocorra. b. Definição: i. > class (Functor t, Foldable t) => Traversable t where ii. > traverse :: Applicative f => (a -> f b) -> t a -> f (t b) c. Definição da instância: i. instance Traversable [] where ii. traverse g [] = pure [] iii. traverse g (x:xs) = pure (:) <*> g x <*> traverse g xs d. Essa classe é útil quando há uma função do tipo a para Maybe b e há uma lista a. Ao utilizar o applicative list, o retorno será do tipo Maybe [b] e não [Maybe b]. e. Por exemplo, dada a função: i. dec :: Int -> Maybe Int ii. dec x | x <= 0 = Nothing | otherwise = Just (x - 1) f. o comando > traverse dec [2,1,0] retornará “Nothing”.
30 GUILHERME FERREIRA GALDINO Applicative Um functor com uma aplicacao, fornecendo operacoes para transformar uma funcao pura em um determinado contexto computacional e uma sequencia de computacoes combinando os seus resultados Contexto computacional = computacao nao deterministica, que pode falhar. class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Essas duas funcoes sao minimas para instanciar um Applicative instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs, x <- xs] > pure (*) <*> [1,2] <*> [3,4] [3,4,6,8] Existem duas possibilidades para implementar applicatives na lista Evento probabilistico exemplo acima, pois retorna todas as possibilidades possiveis Usando zipList, realizando a operação elemento a elemento > pure (+) <*> ZipList [1,2,3] <*> ZipList [4,5] ZipList {getZipList = [5,7]} Traversable Classe de estruturas de dados que podem ser atravessadas executando uma acao para cada elemento. No caso de uma falha na sequencia, nao sera mais computado. Capturar caracteres do teclado Backtracking Sequencia de Applicatives sequenceA :: (Applicative f) => [f a] -> f [a] sequenceA [] = pure [] sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs > sequenceA [[1,2,3],[4,5,6]] [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] > sequenceA [[1,2,3],[4,5,6],[3,4,4],[]] [] class (Functor t, Foldable t) => Traversable where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) A funcao minimia que deve ser implementada um traversable é a traverse, que mapeia cada elemento da estrutura executando uma funcao e coletando os resultados. instance Traversable [] where traverse g [] = pure [] traverse g (x:xs) = pure (:) <*> g x <*> traverse g xs dec :: Int -> Maybe Int dec x | x <= 0 = Nothing | otherwise = Just (x - 1) > traverse dec [1,2,3] Just [0,1,2] > traverse dec [2,1,0] Nothing [BÔNUS] É possível criar uma instância de functor para o Set, já que seria apenas um 'envelope' de uma lista, que já sabemos que mantém a propriedade de identidade e a propriedade de composição de fmaps. Porém, não manteria as propriedades do Set, já que uma função aplicada aos elementos dele, poderia alterar a ordem e/ou a unicidade do conjunto. Um exemplo disso seria esta aplicação: > fmap (rem 3) (Set [1, 2, 3]) {0,1,0}
31 GUSTAVO MATHEUS LIMA SANTOS #Applicative Functors: Também são chamados simplesmente de Applicative. É uma classe que permite a aplicação de Functors em sequência. Esta classe possue 2 métodos: pure e <*>, conforme sua definição: class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Uma forma de pensar no método pure é que ele pega um valor e o coloca em algum tipo de contexto padrão (ou puro), um contexto mínimo que ainda contém esse valor. O método <*> possue a mesma definição da função fmap, ou seja, ele é como um fmap reforçado. É possível implementar uma instância para a classe Maybe: instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx Uma característica importante é que <*> extrai a função do valor à esquerda se este for um Just e faz Map com o valor à direita. Se algum dos parâmetros é Nothing, então o resultado será Nothing. Assim, é possível definir um modelo de programação em que funções puras podem ser aplicadas a argumentos que podem falhar, sem precisar gerenciar a propagação do erro. O Applicative pode ser aplicado a listas, definindo como aplicar um operador em todas as combinações de elementos de duas listas. Também pode ser aplicado em Computação não-determinística, quando as variáveis podem assumir uma lista de valores possíveis. Neste caso o Applicative List retorna todas as possibilidades. # Traversable É uma classe de Tipos que podem ser mapeados. Ela implementa todas as estruturas que podem ser “atravessadas” através de uma sequência. Esta classe é útil quando a sequência é importante e queremos que a computação pare quando uma das aplicações de uma determinada função falhe, retornando Nothing.
24 GaMendes Nessa semana, fomos introduzidos aos Applicative Functors, que são estruturas intermediárias que permitem que cálculos funcionais sejam sequenciados (diferentemente de Functors comuns), mas não permitem o uso de cálculos anteriores, antes que todos os cálculos subsequentes sejam terminados. Para definir melhor, imagine que queremos fazer: > [1,2] + [3,4] [4,5] > (Just 3) + (Just 2) Just 5 Então teríamos, idealmente: fmap0 :: a -> f a fmap1 :: (a -> b) -> f a -> f b fmap2 :: (a -> b -> c) -> f a -> f b -> f c fmap3 :: (a -> b -> c -> d) -> f a -> f b -> f c -> f d E com isso, poderíamos fazer: > fmap2 (+) [1,2] [3,4] [4,5] > fmap2 (+) (Just 3) (Just 2) Just 5 Porém seria trabalhoso demais definir todas essas funções. Poderíamos resolver isso usando currying: pure :: a -> f a aplica :: f (a -> b) -> f a -> f b fmap0 :: a -> fa fmap0 = pure fmap1 :: (a -> b) -> (f a -> f b) fmap1 g x = aplica (pure g) x fmap2 :: (a -> (b -> c)) -> (f a -> (f b -> f c)) fmap2 g x y = aplica (aplica (pure g) x) y Este padrão é tão recorrente que ganhou um nome: Applicative Functor ou simplesmente Applicative, cuja classe de tipo é definida como: class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Depois da introdução aos Applicative Functors, fomos vendo vários usos dessas estruturas. Uma delas são os chamados Traversables, que são tipos que podem ser mapeados. Essa classe é útil quando, por exemplo, temos uma função que mapeia um tipo a para Maybe b e temos uma lista de a.
33 HEBER CAMACHO DESTERRO -O Functor só nos permite usar funções com um parâmetro. -Para não ter que implementar todos os fmap com todos os números de parâmetros, podemos utilizar a classe Applicative. -pure é usado para "encapsular" uma função pura, e transformá-la no contexto computacional desejado. -a classe Traversable é usada quando temos uma lista de um tipo, e queremos mapear a lista inteira em vez de cada elemento separadamente. Útil no tipo de transação onde tudo tem que dar certo ou tudo tem que dar erro, e resultados parciais não servem. [BÔNUS] Dado que na lei dos `Set`s é necessário que os conjuntos devem sempre conter elementos únicos e ordenados, não é possível implementar uma instância de `Functor` para `Set a`, pois a instância de Functor permite como parâmetros valores não-ordenáveis, como os números complexos, e até mesmo não-comparáveis, portanto não seria possível garantir que os elementos do conjunto seriam únicos ou estariam ordenados. Tentei "burlar" isso fazendo uma implementação de fmap que não ordenasse, mas neste caso, apesar de compilar, aplicar fmap em uma função poderia não gerar uma lista ordenada, como no caso da função (^2).
5 HEITOR BELLINI
32 HENRIQUE AUGUSTO DE OLIVEIRA Functors implementa a ideia de mapear cada elemento de uma estrutura sobre uma função. Pode ser visto que a definição de um fmap é bem semelhante dependendo da quantidade de parâmetros que a função recebe. Porém, a medida que vai aumentando o número de parâmetros, fica mais cansativo ter que escrever toda e para cada versão de Functor, a mesma deve ser declarada. Toda essa atividade pode ser facilitada com uma abstração de um nível maior. No uso de Applicative, a ideia de fazer o map da estrutura pode ser abstraída no uso de currying, com o uso dos dois recursos: pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b O pure converte o valor em uma estrutura de tipo f a. A operação utilizando <*>, que aplica a função na estrutura, funcionando como um operador associativo. Eles são escritos entre dois argumentos. O Traversable vem como uma ideia semelhante ao Functor. É utilizado a mesma ideia de mapear os elementos de uma estrutura que é utilizado no map, mas o uso do Traversable pode ser útil em fazer uma generalização diferente deste recurso. Um caso de uso é que, o mapeamento da estrutura só deve ser retornardo com sucesso se cada elemento da estrutura obedeça a função. Caso contrário, o resultado retorna como falha. Um recurso extra que o Traversable traz é o uso do sequenceA, que avalia cada valor de um Applicative e retorno todos esses elementos em conjunto usando uma função identidade. Por exemplo, sequenceA [Just 1, Just 2, Just 3] = Just [1, 2, 3] [BÔNUS] Não é possível implementar Functor's para Set's pois Set's apresentam o tipo Ord, já os Functores não. Um outro problema é que os Set's não obedecem a lei dos Functors fmap (f . g) == fmap f . fmap g para algumas instâncias de Eq. Não necessariamente isso seja verdade com os Set's.
34 HENRIQUE FANTATO SILVA DE ALBUQUERQUE Um functor é uma classe de tipos, que nos auxilia a aplicar uma funçao f qualquer em nossa estrutura de dados, sem alterar a estrutura em si, somente os seus conteúdos. É útil quando queremos aplicar uma função, mas manter a mesma estrutura. Já a classe Traversable nos permite percorrer uma estrutura de dados previamente definida, aplicando uma função f em seus conteúdos, seguindo a ordem em que é necessário para percorrer a estrutura. Um exemplo disso é uma árvore binária balanceada, onde precisamos ir do elemento mais a esquerda(menor), até o elemento mais a direita (maior), seguinto toda a estrutura de nós e folhas da árvore corretamente. [BÔNUS] Não, pois o Data Set deve conter apenas elementos únicos e ordenados, e ao aplicar uma função num Set, onde essa funçao possa retornar elementos repetidos (Exemplo: considere um Set a = Set [1, 2, 3, 4], e um fmap even a, o fmap retornaria [false, true, false, true]) , e o Set eliminaria os repetido e ordenaria os elementos, de tal forma que a regra de composição dons Functors pudesse ser afetada.
35 KELVIN ALVES DOS SANTOS
37 LARISSA COPEL ROTHMAN
38 LEANDRO RIBEIRO DE ALMEIDA
39 LEONARDO SANTIAGO HAMPSHIRE
61 LOUIS PHILLIPE SARDA DUBOIS Applicative permite aplicar um Functor sucessivas vezes de maneira não determinística, ou seja, pode assumir uma lista de possíveis valores. class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Traversable é utilizado para aplicar um Applicable numa dada ordem até uma potêncial falha, ou seja, se um dos applicables for falho, ela vai retornar a falha. class (Functor t, Foldable t) => Traversable where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) Fold instance Applicative (Fold i) where pure o = Fold (\_ -> ()) (\_ -> o) – valor qualquer em unity, valor qualquer o Fold toMonoidF summarizeF <*> Fold toMonoidX summarizeX = Fold toMonoid summarize where toMonoid i = (toMonoidF i, toMonoidX i) – toMonoidF funcao envelopada no Monoid, toMonoidX valor envelopado no Monoid summarize (mF, mX) = summarizeF mF (summarizeX mX) [BÔNUS] Não é possível implementar uma instância Functor para Set devido à algumas instancias peculiares de Eq, como por exemplo: newtype A = A Double deriving Show instance Eq A where (A a) == (A b) = round a == round b instance Ord A where (A a) <= (A b) = a <= b nesse caso, se fizessemos operações como: f (A n) = A (n * 10) g (A n) = A (n / 10) a propriedade fmap (f . g) == fmap f . fmap g não seria verdade
42 LUCAS DAVID VADILHO # Semana 6 ## Functor - Classe de tipo que define `fmap :: (a -> b) -> f a -> f b` - Possuí as seguintes propriedades - `fmap id = id` - `fmap (f . g) == fmap f . fmap g` > In other words, functors serve as adapters between categories that promote code written for the source category to be automatically compatible with the destination category. Functors arise every time we write compatibility layers and adapters between different pieces of software. > https://www.haskellforall.com/2012/09/the-functor-design-pattern.html ### Applicative Classe `Applicative`: generaliza `fmap` para `n` argumentos Usa o padrão `...aplica (aplica(pure g) x) y...` ```haskell class Functor f => Applicative f where pure :: a -> f a -- pure (<*>) :: f (a -> b) -> f a -> f b -- aplica ``` - `Ziplist` para operações elemento a elemento ## Traversable - `sequenceA` ```haskell class (Functor t, Fodable t) => Traversable where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) ``` [Bonus] Para `Set a` ser uma instância de `Functor` ele deve implementar a função `fmap :: (a -> b) -> f a -> f b` com duas propriedades: - `fmap id = id` - `fmap (f . g) == fmap g . fmap g` Usando `{-# LANGUAGE DeriveFunctor #-}` o ghci consegue derivar o functor para `Set`, mas ela não garante as propriedades de `Set`. Algo similar ao seguinte deve funcionar: ```haskell instance Functor (Set a) where fmap f (Set []) = Set [] fmap f (Set (x:xs)) = fromList(f x : fmap f xs) ```
28 LUCAS MAZIM DE SOUSA
41 LUCAS SILVA AMORIM Applicative Functors - Classe de tipos que estende a capacidade de fmap, permitindo uma maior generalização (como um fmap que aceita uma função com multiplos parametros). - Applicative: Classe de tipos, tal que: class Functor f => Applicative f where pure :: a -> f a (envelopa 'a' com f, tornando ela uma função pura no contexto computacional) (<*>) :: f (a -> b) -> f a -> f b (applica uma funcao em contexto puro, a um valor no msm contexto, gerando um novo valor tambem no contexto puro f) - pure (+) <*> Just 3 <*> Just 2 => resulta em Just 5 - Para instanciar Applicative para alguma classe de dados (desde que seja um functor), basta implementar as funções citadas. Transversable: - Funcao sequenceA: (Transversable t, Applicative a) t (f a) -> f (t a). Em outras palavras, (por exemplo Just): sequenceA [Just 2, Just 3, Just 4] -> Just [2, 3, 4] - Caso ocorra alguma falha (Nothing por exemplo), retorna essa falha (comportamento similar ao (m/=>>) do clojure). - Transversable: classe de tipos tal que: class (Functor f, Foldable t) => Transversable where transverse :: Applicative f => (a -> f b) -> t a -> f (t b) (pode ser resumido como sequenceA aplicado a um fmap)
43 LUCAS YUDI FUKAZAWA CASSIN Applicative Classe que implementa a função pure (envolve um valor no functor) e o aplica (<*>) que dado uma função de a para b num contexto e um parâmetro nesse mesmo contexto aplica a função Ex.: Somar 3 valores em um Maybe (f x y z = x + y + z): pure (+) <*> Just 1 <*> Just 2 <*> Just 3 ==> Just 6 Instancia de Applicative para lista faz uma combinação de todas as operações com todos os valores Uma outra implementação para lista é utilizando ZipList. pure (+) <*> ZipList [1,2,3] <*> zipList [4,5] = ZipList [5,7] SequenceA Para lista -> Dado uma lista com elementos envolvidos em um Applicative, retorna uma lista envolvido nesse Applicative. sequenceA [Just 1, Just 2] = Just [1,2] Para isso, precisa existir uma instancia de Travessable Travessable Classe que implementa a função traverse que dado uma função de a para b (envolvido em um contexto) e um parâmetro a, devolve b envolvido no contexto. traverse é um sequenceA aplicado após um fmap [BÔNUS] Não, além do set ser Ord e Functor não. Set não satisfaz a 2a lei de Funtors para algumas instancias de Eq.
36 LUCAS ZOCCHIO Applicative Functors extendem a capacidade de Functores permitindo realizar operações dentro do contexto computacional em que estão. Functores comuns permitem o uso da função fmap para aplicar uma função f a um valor b que é um Functor, retornando um Functor como resultado. Porém, não é possível utilizar funções que já estejam dentro de Functores, o que acaba ocorrendo quando se quer aplicar uma função com mais de um parâmetro, por exemplo. Já um applicative functor, possui a operação <*> que aplica uma função dentro de um Functor a um outro Functor. Essa classe de tipos possui também uma função "pure" que retorna um valor dentro do contexto computacional do Functor. Com isso é possível escrever, por exemplo, (++) <$> Just "abc" <*> Just "def" <*> Nothing, e conseguir avaliar essa expressão como se gostaria, mas não era possível somente com o Functor. Outra classe de tipos que auxilia a trabalhar com Functors e a Traversable. Para instanciá-la é necessário definir uma das funções: sequence A, que toma uma lista de Functores e os combina, retornando um Functor da lista, ou traverse, que toma uma função (a -> f b), ou seja, que toma um valor de um tipo e o coloca no contexto computacional do Functor e um Traversable do tipo a e aplica a função a cada elemento, combinando-os depois. Essa função traverse é parecida com o foldMap para Foldables, porém sendo útil para Functors. [BÔNUS] Não é possível, pois para definir um Functor é necessário um construtor de tipo que aceite qualquer tipo como argumento, mas o Set requer um tipo ordenável, pois para definir fmap, é necessário que se ordene, ao final, a lista produzida.
44 LUCCA IANAGUIVARA KISANUCKI Applicative Functors Applicative currying: pure :: a -> f a aplica :: f (a -> b) -> f a -> f b fmap0 :: a -> fa fmap0 = pure fmap1 :: (a -> b) -> (f a -> f b) fmap1 g x = aplica (pure g) x fmap2 :: (a -> (b -> c)) -> (f a -> (f b -> f c)) fmap2 g x y = aplica (aplica (pure g) x) y class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Applicative Maybe instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx Applicative List instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs, x <- xs] SafeNum + Applicative instance Applicative SafeNum where pure = SafeNum f <*> x = flatten $ fmap (`fmap` x) f Traversable class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) instance Traversable [] where traverse g [] = pure [] traverse g (x:xs) = pure (:) <*> g x <*> traverse g xs
45 LUIZ FELIPE LEAL GOMES AZZOLINI
47 MARCELO CECILIO FAGUNDES DA SILVA FILHO Na semana passada vimos o tipo Functor. Nessa semana vimos algumas classes que generalizam o conceito de Functor, para outros casos. Applicative Functors: Permite realizar operações binárias entre os tipos encapsulados por outro tipo. Exemplo: dado um tipo Maybe a = Just a | Nothing, se criarmos uma instância de Applicative para Maybe, a operação Just 2 + Just 3 será igual a Just 5. A classe Applicative tem duas funções: * pure: Transforma uma função pura em um determinado contexto computacional * <*>: Aplica esse contexto computacional na próxima estrutura. Assim para usar fazer a operação Just 2 + Just 3, fazemos pure (+) <*> Just 2 <*> Just 3. Algo que é bom se atentar é o uso de Applicative em listas, onde a operação não é feita em ordem e sim todas as operações, ou seja, [a, b] `f` [c, d] não é [a `f` c, b `f` d] e sim [a `f` c, a `f` d, b `f` c, b `f` d]. Isso é muito para Computação não-determinística, onde uma variável pode assumir uma lista de possíveis valores ao invés de um único. Traversable: Transforma uma estrutura de um determinado tipo, em um tipo com que contêm esta estrutura. Usando como exemplo o Maybe se tivermos lista de Maybes, [Maybe a], podemos transforma-lo em Maybe [a]. A função que executa esse procedimento é a traverse, que recebe uma função que recebe um tipo a e transforma em um Applicative b, um tipo a dentro de uma estrutura (Foldable e Functor) e retorna um Applicative que contêm a estrutura de tipos b. [Bônus] Não é possível criar uma instância de Functor para Set. Isso por que Set armazena valores em ordem, porém durante a criação da instância de functor não é possível colocar a restrição de tipo Ord.
55 MARIANA MIWA OKUMA MIYASHIRO Applicative Functors - para realizar [1,2]+ [3,4] retornando [4.5], utilizaria-se fmap2 (+) [1,2] [3,4] sendo fmap2: fmap2 :: (a -> b -> c) -> f a -> f b -> f c - alternativamente, podemos usar currying: pure :: a -> f a -- transformando função pura para contexto computacional aplica :: f (a -> b) -> f a -> f b fmap0 = pure fmap1 g x = aplica (pure g) x fmap2 g x y = aplica (aplica (pure g) x) y - tal padrão tem nome: Applicative Functor class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b - ex de uso: pure (+) <*> [1,2] <*> [3,4] - Applicative Maybe: instance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just g) <*> mx = fmap g mx - permite modelo de programação em que funções puras podem ser aplicadas a argumentos que falham, sem propagação de erro - Applicative List: instance Applicative [] where pure x = [x] gs <*> xs = [g x | g <- gs, x <- xs] - apllica um operador em todas as combinações de elementos das listas - Computação não-determinística: - para realizar as operações com os elementos pareados: import Control.Applicative pure (+) <*> ZipList [1,2,3] <*> ZipList [4,5] output: ZipList {getZipList = [5,7]} - SafeNum + Applicative: instance Applicative SafeNum where pure = SafeNum f <*> x = flatten $ fmap (`fmap` x) f Traversable - para realizar uma sequencia de aplicações de uma função g, pode-se utilizar: sequenceA :: (Applicative f) => [f a] -> f [a] sequenceA [] = pure [] sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs - útil quando a ordem de operações importa e podem ocorrer erros em alguma delas exs: capturar caracteres ou backtracking - Traversable: class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) - útil quando temos uma função que mapeia um tipo para Maybe e temos uma lista desse tipo Folds - criar instância de Functor e Applicative para (Fold i) [BÔNUS] Não, pois Set tem constraint Eq e a assinatura de fmap no functor é da forma: fmap :: (a -> b) -> f a -> f b Como não é possível adicionar o constraint em fmap, não é possível fazer ele valer para o Set criado na lista.
48 MATHEUS ALEXANDRE DE SENA Nessa semana aprendemos sobre a classe Applicative, essa classe proporciona alguns benefícios quando comparada a Functors "simples", ela extende a capacidade fmap dos functors, além de permitir funções ainda mais generalistas, com mais argumentos, com isso podemos criar além do fmap convencional, outras generalizações de fmap com mais argumentos, essa classe Applicative é definida com um "pure", que recebe um "a" e retorna esse "a" após ser aplicado em uma função "f", e um operador "aplica" (<*>), que recebe "f (a -> b)", e aplica essa função "f" em "b" e em "a". Além disso aprendemos sobre Traversable, que é uma função para tipos que podem ser mapeados, é muito útil quando precisamos fazer alguma computação que a sequencia é importante, ou seja, aplicar funções sequencialmente, e parar caso alguma falhe. [BÔNUS] é impossível aplicar uma instancia de Functor para Set, respeitando as leis dos functors e dos Sets, porque a instancia de Functor não tem a definição de Ord, necessária para Set.
50 MIGUEL MIRA FONSECA A classe de tipo Applicative permite generalizar o conceito de Functor para receber funções com mais de um argumento. Ao invés de ter uma função fmap, podemos ter fmap2, fmap3 e assim por diante. E podemos também definir a função fmap0, também chamada de pure, que pode ser definido da forma fmap0 :: a -> f a. A ideia da classe Applicative é abstrair essa generalização e evitar ter que construir essas funções de forma manual, através da função aplica, da forma aplica :: f (a -> b) -> f a -> f b. Assim fmap2 g x y será da forma aplica (aplica (pure g) x) y. Para fmap3 basta repetir o operador aplica. Como exemplo, retornando ao tipo customizado SafeNum criado nas últimas aulas, podemos criar uma instancia de Applicative para SafeNum. Com isso podemos implementar funções como safeAdd e safeDiv de forma a receber mais de um parâmetro SafeNum. Uma classe de tipo mais fina seria a classe Traversable que permite controlar a travessia sobre uma sequência, de tal modo que podemos fazer uma tratativa especifica para casos de falha por exemplo. A função sequenceA definida pela forma sequenceA :: t (f a) -> f (t a). Onde se f for do tipo Maybe, iremos trazer esse contexto dos elementos individuais a para a lista inteira. Como exemplo, podemos simplificar a execução da ação de logging sobre as funções do nosso programa através do uso do Travesable Writter, que permite deixar separado a parte de processamento da função e parte de log em duas partes separadas (no caso, através de uma função recursiva). Também podemos modelar o processo de Fold através de uma ADT.
53 NATALIA LEITE VARES DE SOUZA APPLICATIVE FUNCTORS Applicative é uma classe intermediária entre Functor e Monad. Como os monóides, os applicative functors são functores com leis e operações extras. Na semana anterior aprendemos sobre Functors e o uso do fmap, porém por mais útil que seja, fmap não ajuda muito se quisermos aplicar uma função de dois argumentos a valores funcionais. Por exemplo, se quisermos somar Just 2 e Just 3. - Métodos Applicative Functors (<*>) é um dos métodos de Applicative, a classe de tipo de applicative functors. Podemos escrever a soma do exemplo anterior, como (+) <$> Just 2 <*> Just 3. Onde <$> é sinônimo do fmap. Dentro da estrutura de Applicative Functor temos também a implementação pure, que nesse contexto tem o significado que estamos transformando uma função pura em um determinado contexto computacional. TRAVERSABLE O Traversable é um tipo de Foldable atualizado. O Foldable confere a capacidade de passar pela estrutura processando os elementos, com o uso do foldr, mas sem aproveitar o formato. Já o Traversable permite que sejam realizados os processamentos, mas com preservação da forma. Essa classe é útil quando, por exemplo, temos uma função que mapeia um tipo a para Maybe b e temos uma lista de a FOLD A partir do Foldable podemos criar um tipo Fold, e consequentemente podemos criar uma instância de Functor e uma instância de Applicative.
52 NATALIA REGINA COSTANZI
51 NATHALIA CORREA DOS SANTOS
60 PAULO GABRIEL MASSA
56 PAULO HENRIQUE EIJI HAYASHIDA om a classe Applicative, assim como foi visto no calculo lambda pode-se definir as funções pure e aplica(<*>) Onde a função pura pega um elemento de um tipo e retornar uma função aplicada à esse elemento, já a função aplica pega uma função uma de a para b e uma função aplicada em a e retorna uma função aplicada em b. Permitindo criar operadores que implemetam, por exemplo, somas de variaveis do tipo Maybe pure (+) <*> (Just 3) <*> (Just2) que retorna Just 5, pure no inicio envolve o resultado da expressão (+) <*> (Just 3) <*> (Just2) para o resultado retorne dentro de um Just Para utilizar para o tipo Maybe deve se definir pure x = Just x, dado um x aplica Just no valor x Nothing <*> _ = Nothing, aplicar uma função a Nothing como não possui um valor deve retornar o proprio Nothing (Just f) <*> mx = fmap g mx, aplica o g nos valores de mx. Com a função sequenceA aplica uma dada funçãos a uma lista na sequencia em que se aparecem os elementos, caso a computação falhar para um dos dados ele retorna Nothing A classe Traversable é util quando se quer, por exemplo mapear uma lista de tipos a para Maybe b, sendo que o retorna da função não é uma lista contendo Maybe b, mas sim um Maybe lista de b. Ou seja uma lista envolvida em uma função Maybe.
59 PEDRO ANTUNES NEGRÃO Na sexta semana de aula foi apresentado as classes Applicative, Traversable e Applicative Folds, dando exemplos e definições de cada um deles. Começando pelo Applicative, também chamado de Applicative Functor, é uma classe que nos permite generalizar ainda mais a função fmap, sendo que agora é possível passar mais de um argumento para as funções. É possível criar manualmente essas instâncias do functor, mas isso seria muito trabalhoso, por isso que a utilização dessa classe facilita a programação. Ela utiliza duas funções, pure e "aplica" (<*>). Pure tem esse nome porque ele pega um valor puro e transforma em um contexto computacional (Maybe, Lista, Tree, etc.). Já o "aplica" que é denotado pelo operador <*> ele pega um função envolvida em um functor, um valor a envolvido em um funtor e devolve um valor b envolvido em um functor. Apenas com essas funções é possível definir um fmap mais genérico, que é o objetivo da utilização dessa classe. O professor explica alguns exemplos utilizando listas, maybe, e até mesmo usando o tipo SafeNum criado em aulas anteriores. Assinaturas: pure :: a -> f a aplica :: f (a -> b) -> f a -> f b Já para o Traversable, ela é utilizada quando queremos construir algo que retorne Nothing ou vazio quando ele encontrar um erro durante o uso de um Applicative em uma lista. Com isso, o conceito de avaliação preguiçosa é mantida, já que não é necessário prosseguir com a avaliação da lista inteira caso encontre erro no meio dela. Um exemplo citado pelo professor é mostrado na seguinte assinatura do traverse: traverse :: Applicative f => (a -> f b) -> t a -> f (t b) Sendo f = Maybe e t = Lista Por fim, na aula sobre Applicative Folds, o professor retornou ao material no qual ele havia criado um tipo Fold e criou instâncias do Functor e Applicative.
57 PEDRO BRAGA DOS SANTOS BACELLAR [BÔNUS] Não é possível implementar um functor para um set. O set precisa que seu invariante elencado na lista 5 seja mantido SEMPRE. O functor aplica uma função em cada elemento de um tipo paramétrico e apenas isso. Ao aplicar uma função qualquer sobre o set, pode ser que o invariante seja quebrado.
58 PEDRO MACHADO NERY DOS SANTOS Applicative Functors generalizam fmaps de Functors para funções com mais argumentos aplicadas a tipos paramétricos. Algo similar a pegar funções como fmap2:: (a->b->c) -> f a -> f b -> f c Um Aplicative é definido para um functor f e envolve uma variável no contexto desse functor e aplica fmap da maneira esperada aos vários argumentos. class Functor f => Applicative f where pure :: a -> f a (<*>) :: f(a->b) -> f a -> f b Exemplo: instance Applicative Maybe where pure = Just -- envolve valor no contexto Maybe Nothing <*> _ = Nothing -- aplicar mais valores com um Nothing resulta em Nothing (Just g) <*> mx = fmap g mx -- função g no contexto Just pode ser aplicada emum Maybe x Traversable é uma classe que generaliza a aplicação de uma função em objetos transponíveis ou "percorríveis", mas tratando este objeto como um todo. Podem ser utilizados junto a aplicativos na função sequenceA. Assim como Aplicativos, Traversables podem ser utilizados em computações não determinísticas que consideram probabilidade de falha. class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a -> f b) -> t a -> f (t b) Um traverse também pode ser entendido como um sequenceA aplicado após um fmap ou <$> traverse. A classe Traversable permite a composição de tipos mapeados de uma forma mais natural e sobre contextos específicos de tipos paramétricos. Funções como () Unit e pure podem ser utilizadas para formalização dessas composições de maneira a condicionar o tipo final traversable à consideração das estruturas compostas como um todo único sobre um tipo paramétrico como lista ou árvore. [BÔNUS] Sim, é possível criar uma instância de Functor para o Set a da última lista. Isto é, é possível modelar comportamentos a serem aplicados se mantendo a estrutura de Set a e atendendo à propriedades de identidade e composição. (Identity: fmap id == id; Composition: fmap (f . g) == fmap f . fmap g). Isso pode ser feito por exemplo, aplicando funções sobre todos os elementos de um Set (dobrar elementos, aplicar somas, etc). Algo como o código a seguir poderia ser feito instance Functor Set where fmap f (Set a) = Set (map f a)
65 PEDRO REGIO SHOJI Applicative Functors é uma classe de tipo que extende as capacidades do fmap presente nos Functors comuns. Dessa forma, ele pode ser generalizado ainda mais aplicando funções com mais de 1 argumento à estrutura alvo. Esse comportamento é definido através de uma função e um operador: pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b Onde pure envolve o valor passado na estrutura do tipo daquela instancia de Applicative Functor E o operador referido como "aplica" nas aulas aplica os valores de a que estão envoltos por f aos valores de b também envoltos por f. Uma observação a ser feita é que o operador <*> para duas listas xs e ys não retorna apenas a lista de x[0] aplicado com y[0], x[1] com y[1]... e sim todas as possíveis dados os valores das 2 listas. O comportamento descrito inicialmente acima é resultado do Applicative Functor de ZipList A classe de tipo Traversable tem a ideia de processar um tipo de dado de forma sequencial. Isto é muito útil para capturar possíveis erros entre operações pois o tipo os resultados da operações entre os valores do Traversable são "carregados" para o resultado da operação. No exemplo dado em aula, a função sequenceA aplicado em uma lista onde um dos elementos é Nothing, retorna Nothing assim que encontra o primeiro elemento Nothing. No caso, uma lista de Maybe se tornou em um Maybe de lista. Bônus: Não é possível criar uma instância de Functor para um Set, pois um Set requer que seus elementos estejam em Ord o que impede que eles seja um Functor. Isso porque a função fmap de um functor (Functor f => (a -> b) -> f a -> f b) não possui restrições quanto ao tipo de "a" ou "b".
62 PIETRO DI CONSOLO GREGORIO A classe de tipo Applicative estende a capacidade do fmap, fazendo com que seja possível a aplicação de funções que usam mais argumentos. Essa classe de tipo define a função pure, que gera um valor puro dentro do contexto computacional, e o operador aplica (<*>) definido na forma f (a -> b) -> f a -> f b. Quando instanciamos Applicative para o tipo Maybe, podemos usar funções puras em argumentos que podem falhar sem precisar gerenciar a propagação do erro, por exemplo uma divisão por zero retornaria Nothing. Em listas o Applicative define como aplicar um operador em todas as combinações de elementos de duas listas, o que seria útil em computação não-determinística, outra interpretação do Applicative de listas é a operação elemento a elemento pareados. A classe de tipo Traversable implementa os tipos que podem ser atravessadas através de uma sequência, ou seja, tipos que podem ser mapeados. Uma das utilidades dessa classe são em casos onde temos uma função que mapeia um tipo a para um tipo Maybe b e desejamos ter no final um Maybe [b] e não um [Maybe b], dessa forma, se alguma aplicação da sequência falhar, será retornado um Nothing. Aos criar uma instância de Functor e Applicative para o Fold, é possível combinar diferentes folds para formar folds mais complexos e eficientes, já que as operações são feitas em paralelo e em uma única passagem na estrutura de dados. [BÔNUS] Não é possível, pois existe a possibilidade de uma função passada ao fmap alterar os elementos de forma que não seja mais respeitado as leis do Set, necessitando uma reestruturação do Set, o que desrespeitaria as leis do Functor, que define fmap na forma (a -> b) -> f a -> f b.
12 RAFAEL BRUNO FERREIRA FIGUEIREDO
63 RAFAEL PAUWELS DE MACEDO Nessa semana estudamos a classe de tipo applicative, que expande nossa capacidade de criar um functor com definições de fmap diferentes, do tipo, por exemplo, fmap2 a b -> c. As classes Applicative são especialmente úteis para aplicar funções sobre instâncias de functors usando apenas a função "pure" e o operador aplica representado por "<*>", dessa forma, caso eu queira somar dois Just posso usar a sintaxe "pure (+) <*> Just 1 <*> Just 5" e a resposta será "Just 6". Importante notar que o applicative para listas se comporta como uma list comprehension do tipo [g x | g <- gs, x <- xs] Então [(+2)] <*> [1,2] resultaria na lista [3,4] A segunda classe que estudamos foi a traversable, que possibilita transformarmos t (f a) em f (t a), por exemplo, uma lista de maybe a se torna maybe uma lista de a. A classe traversable expõe a função traverse. Dentro dos casos de uso e exemplos para os traversables vimos o bin2dec, uma função que traversa uma string binária e devolve um número inteiro. Usamos uma classe que chamamos de Writer e criamos instâncias de Functor e Applicative para essa classe. Aplicando o conhecimnento dessas aulas voltamos ao exemplo onde defimos os operadores <+> e <.> para folds e reescrevemos esse comportamento usando instâncias de Functor e Applicative, com isso vimos a aplicação dentro de funções como o avg (/) <$> sum <*> length, calculando a média em uma única passagem.
64 RAPHAEL RAMOS DA SILVA --------------------------------------------------- Applicative ----------------------------------------------- Classe de tipo Applicative (generaliza ainda mais o fmap, com mais argumentos) - exige a definição das funções pure e (<*>) função puro: recebe um valor puro e o envolve em algum contexto computacional pure :: a → f a (3 → Just 3) (5 → [5]) Função aplica: pega uma função (a→ b) envolvida em um contexto computacional, um a envolvido em um functor e devolve um b envolvido no functor aplica :: f (a → b) → f a → f b (também representado por (<*>)) Exemplo: funSoma x y z = x + y + z pure funSoma <*> Just 3 <*> Just 5 <*> Just 8 retorna Just 16 Exemplo: instância de Applicative para Maybe pure x = Just x Nothing <*> _ = Nothing Just g <*> mx = fmap g mx ----------------------------------------------------- Traversable ----------------------------------------------- Útil, por exemplo, quando temos uma função que mapeia um tipo a para Maybe b e temos uma lista de a. Exemplo: Em vez de retornar [Just 1, Just 2], retornará Just [1,2] class (Functor t, Foldable t) => Traversable t where traverse :: Applicative f => (a → f b) → t a → f (t b) ------------------------------------ Instância de Applicative para Folds ------------------------------------ - Combinação de Folds instance Applicative (Fold i) where pure x = Fold (\_ → ()) (\_ → x) Fold mF sF <*> Fold mX sX = Fold toMonoid summarize where toMonoid i = (mF i, mX i) summarize (f, x) = sF f (sX x)
40 RENAN FERREIRA LIMA Em Haskell há uma classe denominada Applicative que, dado um functor f, é definida pela função pure que recebe um número e gera um valor puro dentro do contexto computacional, e o operador aplica (<*>) que recebe um pure e uma função, devolvendo um pure resultante da função. Em um exemplo usando listas, onde a entrada é composta por duas listas e a função é soma, o resultado vai ser a combinação de soma entre todos os elementos das duas listas. É possível criar instâncias para Applicative e declarar funções que respeitem as propriedades esperada, por isso é importante que a classe receba um Functor, pois há instâncias que necessitam do fmap para que as propriedades sejam atendidas, também é possível criar uma instância. Voltando ao exemplo de listas, para operações elemento a elemento há o ZipList que descarta eventuais elementos sobressalentes, devolvendo uma lista do tamanho da menor lista de entrada. Uma outra classe é a Traversable, que dado um t que é um Functor e também um Foldable, é possível criar uma função traverse, que através de um applicative f, retorna um f(t b). Essa classe é útil em situações que deseja-se, por exemplo, ter um retorno de um maybe lista de b e não um lista maybe b, dado uma entrada composta por uma lista de a e um maybe b. Voltando ao Applicative é possível utilizá-los com Folds, de forma a construir folds mais complexos, sem perder poder computacional. [Bonus] Não é possível criar uma instância de Functor para Set a, pois Set requer um tipo ordenado, ou seja há uma restrição do tipo de entrada, enquanto que um functor não tem restrição de entrada.
66 RENAN GONCALVES MIRANDA Applicative Functors É uma classe de tipo que estende a capacidade da fmap, permitindo a aplicação de funções com mais argumentos, ganhando uma possibilidade ainda maior na generalização. O Applicative é uma classe que dado um Functor f (f deve ser um Functor), o Applicative de f é definido pela função pure (que gera uma função puro dentro do contexto computacional) e pelo operador "<*>" (f (a -> b) -> f a -> f b). Instancia de Applicative para SafeNum pode ser feita da seguinte forma: pure x = SafeNum x f <*> x = flatten $ fmap (<$> x) f Traversable É uma classe que implementa todas as estruturas que podem ser atravessadas através de uma sequência. útil quando temos uma função que mapeia um tipo x para Maybe y e teremos uma lista de Maybe ( Maybe [y]). Utilizado para interromper o processamento do código caso esteja analisando uma lista e um dos casos falhe, com isso não faz sentido continuar o processamento, retornando que o processo falhou, como exemplo, caso uma lista retorne um Nothing para o terceiro elemento de uma lista de 10, o processo será interrompido, retornando o Nothing. Um traverse nada mais é que um sequenceA aplicado posteriormente a uma fmap (traverse = sequenceA $ fmap)
67 TAMIRES CHRISTYNE DA SILVA
69 VINICIUS DE OLIVEIRA CAMPOS DOS REIS
0 VITOR MARINI BLASELBAUER
70 VITOR RUBENS SNIQUER LEAO MARTINS
68 VITTORIA ARIEL DOS SANTOS BOROTTO => Functor: classe de tipo que generaliza Map para outras estruturas Funcoes que fazem com que as funcoes sejam aplicaveis a outras estruturas alem de uma lista, tipo mais generico. Note que f é algo parametrico class Functor f where fmap :: (a -> b) -> (f a -> f b) Functor Map precisa obedecer: fmap id = id fmap f . fmap g = fmap (f.g) Podemos tambem substituir fmap por um operador <$> (+1) <$> [1,2,3] [2,3,4] Definindo Functor fundamentais Quase todos os tipos que vimos possuem uma instancia de Functor Como se fosse uma algebra dos Functors Funcionando como um Monoid de uma funcao generica, e dado generico => Aritmetica Segura com Functor Podemos ter exceptions, em operacoes aritmeticas, como divisao por zero, ate mesmo ultrapassar o numero de bits de um tipo de dado. p.e 64+1bits de Int -> Overflow Para tratar isso existe a aritmetica segura. data SafeNum a = NaN | NegInf| PosInf | SafeNum a deriving Show - NegInf e PosInf - utilizado em caso de overflow - NaN - Not a Number: utilizado em caso de operações aritméticas inválidas => Applicative Functors Ficar definindo functors para todas as funcoes se torna trabalhoso, para facilitar usamos o currying, estruturando a aplicacao do functor. O Applicative pode ser usado com varios tipos, e contextos, por exemplo o Maybe, List e dessa forma combinarmos. => Traversable Uma sequencia de aplicacao de uma funcao aplicada em uma ordem, no caso da avaliacao preguicosa, cada elemento avalidado se falhar nao ira continuar. O Traversable permite um mapeamento de tipos podendo ser util em casos de uma funcao mapear um tipo para outro. [BÔNUS] Sim é possivel implementar uma instancia de Functor para o Set a, visto na lista 5, respeitando as leis dos Funtors e Sets, que é a identidade e funcao de funcao, O functor possibilita uma funcao ser aplicada a outras estruturas de tipos, por exemplo o Set a. Por exemplo poderiamos fazer Aproximadamente isso: instance Functor Set where fmap _ (Set []) = Set [] fmap f (Set a) = Set (fmap f a)
71 WALTER OSCAR TRUJILO
72 WESLEY AXEL DE BARROS Para esta semana 06, vimos um topico importante para o estudo de Haskell na disciplina de Paradigmas de Programação. Verificamos o conceito de Applicative Functors, que é uma classe criada para o processo de curring em diversas funções que simplificam um código, fazendo com que seja possivel aplicar uma função em um conjunto de dados de diversos tipos, de maneira mais simplificada. Utilizamos "pure" como uma função pura em um determinada instancia aonde será uma função pura no contexto e (<*>) para determinar a função. Analisamos a utilização do Applicative no tipo Safenum, que acabou simplificando a maneir que colocamos as funções no codigo. Estudamos o conceito também de Traversable, que é uma classe de funções parecida com as classes fold, aonde se aplica um functor em uma estrutura da esquerda para a direita. Aonde por exemplo, em um tipo [a] para um maybe b, aonde aplicado uma função nessa lista de tipo [a], se obtem um maybe [b]. Com o Traversable, com a aplicação do functor na estrutura, verifica-se o resultado a cada aplicação, para que por exemplo, caso o compilador encontrasse um resultado que anulasse toda a lista de resultados aplicados de uma função em uma lista, ele iria parar de compilar o resto e já exibir o resultado final que anulou toda aplicação. [BÔNUS] Não, não é possivel, pois na construção e ordenação dos elementos presentes em qualquer "x" sendo esse "x" um "set a", é necessario que os mesmos estejam ordenados/arranjados, e com a aplicação de qualquer função functor nesse conjunto de elementos do "set a", faria com que fosse possivel desordenar/desaranjar esses elementos.
29 WILLIAM DE SOUZA GOMES
73 WILLIAM SENA SILVA
18 francesquini