1 |
ALLEF KRISTIAN TAVARES ROCHA |
|
2 |
ANGELO MAEDA ROJAS |
Monads – Parte 1
Bind
>== :: m a -> (a -> m b) -> m b
A class monads é definida como
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
Return :: a -> m a
Monoid de Monad
Em teoria das categorias um Monad pode ser visto como um Monoid das categorias dos Functors.
1 - O elemento identidade é o return
2- O operador associativo é uma variação de >>= com a assinatura:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
Generalizando, uma expressão construída com o operador (>>=) tem a seguinte estrutura
m1 >>= \x1 ->
m2 >>= \x2 ->
.
.
.
mn >>= \xn ->
f x1 x2 … xn
A expressão generalizada acima pode ser melhorada (Syntactic Sugar) com a expressão abaixo
do x1 <- m1
x2 <- m2
.
.
.
xn <- mn
f x1 x2 ... xn
Segue abaixo a instância de Monad para o tipo Maybe
Instance Monad Maybe where
Nothing >>= _ = Nothing
(Just x) >>= f = f x
Mesmo Haskell sendo considerado puro, nenhum programa possui zero de efeitos colaterais. Se fosse assim seria uma linguagem com poucas utilidades.
Funções impuras são necessárias para diversos casos. Esses casos irão começar nesse resumo e terminar no próximo!
1 - Parcialidade
Quando temos uma função que pode não terminar
Valor bottom: _|_
f :: a -> Bool
Retorna True, False ou _|_
2 - Não-determinismo
Quando uma função pode retornar diferentes saídas dependendo de certas condições internas ou externas.
3 – Exceções
Quando ocorre um erro
Podemos utilizar Maybe para isso, que a exceção retornar o valor “Nothing”. Se quisermos especificar o erro podemos utilizar o dado Either.
|
3 |
ANTONIO DUARTE CANTANHEDE NETO |
|
6 |
BRUNA ISHIDA |
Monads são um tipo de estratégia para resolver algum problema que repete com frequência, o conceito é bem
parecido com a metodologia "características transversais". É possível pensar em Monads como estratégias de combinar
computação em questões mais complexas de computação, uma metodologia para estruturar computação em termos de valores
e sequências de computação utilizando de valores tipados.
Em alguns aspectos é possível um Monad ser visto como um Monoid, uma vez que o mesmo possui o return como elemento de
identidade e é possível duas funções que transformam um valor puro em um Monad serem combinadas para realizarem outra
função.É possível, também, utilizar do SafeNum nos Monad
Mesmo Haskell sendo denominada uma linguagem "puramente funcional", existem alguns limites em que a mesma consegue chegar,
sendo possível existir alguns tipode de funções impuras que podem ser utilizadas em diferentes necessidades.
- Parcialidade: quando uma função não pode finalizar, ou seja, pode retornar um valor _I_
- Não determinístico: retorna valores diferentes dependendo de questões internas ou externas.
- Estado: valores no Haskell são puros e imutáveis, porém, é possivel adicionar um estado atual na declaração da função
Existem funções de alta ordem para os Monads, as quais existem na biblioteca Control.Monad. Com o mesmo é possível
implementar diversos métodos "monádicos", como por exemplo: filterM que é um filter, mapM que é um map |
7 |
BRUNA MIRELLI XAVIER GONCALVES |
11.1 Classe Monad
> Operações sequenciais que tratam seus efeitos.
> Possui o operador bind que funciona como uma função
vinculadora do resultado da computação de um valor
ao argumento de uma outra função.
> Bind:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
11.2 SafeNum + Monad
> Podemos criar uma instância de Monad para SafeNum
instance Monad SafeNum where
(SafeNum v) >>= f = f v
snv >>= _ = boxedCoerce snv
11.3 Monad Lista
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
11.4 Monad Either
instance Monad (Either a) where
(Left msg) >>= f = Left msg -- propagacao da msg de erro
(Right x) >>= f = f x --aplicacao da funcao
11.5 Monad Reader
Dado um tipo de dado
data Reader e a = Reader (e -> a)
instance Monad (Reader e) where
-- (>>=) :: Reader e a -> (a -> Reader e b) -> Reader e b
ra >>= arb =
Reader (\e -> let a = runReader ra e -- a
rb = arb a -- Reader e b
in runReader rb e)
11.6 Monad Writer
data Writer w a = Writer a w
deriving Show
instance (Monoid w) => Monad (Writer w) where
-- (Writer w a) -> (a -> Writer w b) -> (Writer w b)
(Writer a w) >>= k = let (b, w') = runWriter (k a)
in Writer b (w <> w')
11.7 Monad State
data State s a = State (s -> (a, s))
deriving Show
instance Monad (State s) where
-- (>>=) :: State s a -> (a -> State s b) -> State s b
sa >>= f = State (\s -> let (a, s1) = runState sa s
sb = f a
in runState sb s1)
11.8 Monad IO
newtype IO a = newtype ST a = State -> (a, State)
type State = Environment
Funções de entrada e saída: IO actions
11.9 Monads: Funções de Alta Ordem
A biblioteca Control.Monad oferece versões de funções de alta ordem para Monads,
como mapM, filterM, etc. |
8 |
BRUNO STORER FRANCO MARTINS |
Nessa semana aprendemos sobre monads que se tratam de monoids dentro da caracterização Functor , com neste caso chamando ‘return’ de elemento identidade e o operador peixe (>=>) servindo de associativo.
Abaixo segue a declaração do eval com esses termos para :
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
Um Syntactic sugar comum é utilizar a palavra do, modificando eval para:
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = do n <- eval x
m <- eval y
safeDiv n m
Com isso podemos declarar a classe Monad:
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
Em seguida aprendemos sobre a necessidade de funções não puras. Haskell pode ser uma linguagem puramente funcional, mas algumas funções impuras são necessárias como o print de valores na tela, senão o programa não tem significado prático.
Principais usos de funções puras estão no uso para parcialidade (em funções que podem não terminar), não-determinismo (quando funções podem retornar diversos valores para uma mesma entrada), efeitos colaterais, exceções , continuações e IOS.
Monads são usados para lidar com todos esses casos. Um exemplo, no caso de exceções:
Declaramos Either:
data Either a b = Left a | Right b
Left é o log de erro e Right o valor esperado caso não haja erros.
Declara-se:
instance Monad (Either a) where
(Left x) >>= f = Left x
(Right x) >>= f = f x
Assim, com as operações podem ser feitas propagando o log de erros. Um exemplo seria aplicação no uso de cálculo de logaritmos, veja:
safeLog :: (Show a, Ord a, Eq a, Floating a) => a -> Either String a
safeLog x
| x <= 0 = Left ("Log invalido: " ++ show x)
| otherwise = Right (log x)
|
9 |
CAIO ARGENTINO DE OLIVEIRA |
classe Monad:
-definição da classe:
-class Monad m where
(>>=) :: m a -> (a -> m b ) -> m b
return :: a -> m a
-exemplo de uma instância de um Monad:
-instance Monad Maybe where
mx >>= g = case mx of
Nothing -> Nothing
Just x -> g x
-onde ">>=" na definição de um Monad é chamado operador bind;
do-notation:
-syntactic sugar para lidar com monads e o operador bind de forma mais simplificada
-o trecho:
m1 >>= \x1 ->
m2 >>= \x2 ->
m3 >>= \x3 ->
f x1 x2 x3
- pode ser reescrito utilizando-se do-notation, ficando na seguinte forma:
do x1 <- m1
x2 <- m2
x3 <- m3
f x1 x2 x3
|
5 |
CAIO HENRIQUE DOS SANTOS RIBEIRO |
|
38 |
DIOGO AKIO BALBONI MIYAKE |
|
11 |
EDUARDO MACIEL DE SOUZA |
Essa semana começamos a aprender sobre Monads, que é uma maneira de encadear processamentos que necessitam do resultado do processamento anterior. Essa classe também pode ser muito emprega para tratamento de erros.
Vimos que quando possuímos operações que podem causar erros, não podemos realizá-las em qualuqer ordem, pois para uma operação ocorrer devemos ter a garantia de que os elementos que a compõem serão válidos. Tratar esses casos com o uso de 'case of' acaba resultando em códigos de difícil leitura e muitas vezes com encadeamentos complexos.
Para capturar esse padrão de encadeamento de 'case of' utilizamos a classe Monad, que declara o uso do operador bind, que devemos implementar. Esse operador retira um valor a de dentro de um container e aplica uma função f sobre ele, resultando em um valor b envolto no mesmo container.
Existe um sintatic sugar para Monads, o do-notation que quando utilizado deixa o código muito parecido com códigos do paradigma imperativo.
Podemos usar monads com o tipo Either, pois dessa forma podemos seguir uma sequência de computações pelo 'caminho da direita' e armazenar uma mensagem de erro no 'caminho da esquerda', assim podemos ter uma mensagem de erro que nos indica em que ponto da operação obtivemos a falha.
Monads também são utilizados para tabalhar com efeitos colaterais, como leitura e escrita de arquivos, impressões ou mudança de estados. |
12 |
FELIPE PONSANO FRANKE |
|
17 |
GABRIEL ALBANO SANTOS |
|
18 |
GABRIEL BELLOMI MEALE |
|
13 |
GABRIEL DE MELLO FIALI |
Monads:
- Permitem a generalização de sequenciamento de computações para funções que geram efeitos colaterais. Contribuição do Haskell para outras linguagens.
- Trata-se de uma forma de preservar a pureza dos programas.
- Utiliza-se do operador bind (>>=) para manipular as instâncias de tipos.
- Pode operar através de expressões lambda ou do um sintax sugar "do notation".
- Melhora a clareza do código, além de o tornar mais enxuto.
- Também é possível se utilizar do pattern matching como outra forma de implementar o bind.
- Depende também da classe Applicative, contando com uma função return, análoga à função pure, além de (>>=).
- Efeitos colaterais:
- Parcialidade: funções que podem não terminar (não são totais).
- Valor bottom (_|_): Sinalização de que o tipo de dado pode falhar.
- Não-determinismo: retornos diferentes dependendo das condições durante a execução.
- Either: uma forma de realizar o tratamento de funções que geram exceções e mantendo a informação gerada do lado do erro. O tipo é dividido em 2, com o lado esquerdo reservado para o tratamento e o direito para os valores de fato.
(Continuação na parte II...) |
15 |
GABRIEL MENDONÇA FARIAS |
Monads são meios de implementar formas de gravar, acessar e imprimir arquivos mantendo a pureza das linguagens funcionais. Em outras palavras, Monad pode ser visto como um Monoid aplicado aos Functors.
Para aplicar uma sequência de funções dependentes entre si, pode se usar do bind, que usa funções do tipo Maybe a -> (a -> Maybe b) -> Maybe b
Monads tem como aplicação combinar duas funções de valor puro e gerar terceira função com os valores anteriores, gerando uma operação do tipo Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
SasfeNum é uma função em que mesmo que o valor apresente um erro, não gerará o fim da execução do programa, mas sim uma alternativa de saída. Desta forma a implementação de SafeNum e Monad juntas permite a aplicação de uma série de funções do tipo Monad, com segurança de funcionamento do programa provida pelo SafeNum.
A aplicação de uma série de funções que não sejam interdependentes entre si pode ser otimizada com o uso de um Applicative.
Destro da linguagem Haskell, ainda existem funções impuras, para implementação de funções parciais que podem não terminar, divisão por zero, ou estados somente de leitura, por exemplo. Pois alteram o estado atual do sistema. O mesmo ocorre com funções do tipo IO, pois mesmo que executadas da mesma maneira e em sequência, podem gerar saídas diferentes.
A aplicação do Maybe pode indicar que houve um problema, mas ao implementar a função Either, pode-se ter acesso ao ponto em que a falha ocorreu.
Também é possível transformar um estado utilizando o State, que recebe um estado (ou um estado e um valor) e retorna na saída um novo valor e um novo estado.
Existem funções de alta ordem para Monads, na biblioteca Control.Monad.
|
16 |
GABRIEL MURAKAMI ALVES |
Estudando sobre Functors foi introduzido a possibilidade de mapear funções com
diferentes tipos de dados. Isto é, dado uma função a -> b e um tipo f a, mapearmos
para f b. O Applicative extendia um comportamento do Functor, fazendo com que a
função inicial possa estar dentro de um contexto próprio, ou seja, já mapeada como
f (a -> b) e da mesma forma termos um tipo f a e mapeado para f b.
As Monads extendem o comportamento dos Applicative Functor. Sua assintura sai
de um tipo m b, aplicamos em uma função que nos leva de a -> m b e tem como retorno
o tipo m b. O seu operador é o (>>=), chamado de bind.
Essencialmente temos duas implementações para as estruturas de um Monad. Uma
estrutura utilizando bins e a chamada do-notation. Sendo que as duas estruturas
evidenciam a natureza sequeêncial do Monad e o do-notation é basicamente um
Syntactic Sugar para a estrutura utilizando binds.
Com binds temos algo como:
m1 >>= \x1 ->
m2 >> = \x2 ->
f x1 x2
e com do-notation temos:
do x1 <- m1
x2 <- m2
f x1 x2
|
35 |
GABRIEL SILVESTRE MANCINI |
|
20 |
GEORGE HARRISON ROCHA |
• Monads
- Permite uma generalização de sequenciamento de computação quando precisamos de funções que geram efeitos colaterais;
- Sequência de computações com efeito em que uma computação depende da anterior;
- Pode ser visto como um Monoid das categorias dos Functors;
- Classe Monad:
class Applicative m => Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
- O operador bind (>>=) garante que se uma computação falhar, ela para imediatamente e reporta a falha;
- A função return é uma redefinição da função pure.
- Syntactic Sugar: Uma expressão construída com o operador bind (>>=) pode ser escrita com a notação chamada do-notation;
- Em aula foi feita uma versão com Monad do exercício SafeNum;
- Nessa semana vimos aplicações de Monad lista e Monad Either.
|
21 |
GIANCARLO KAMI DELL ARINGA VIANA |
|
42 |
GIOVANNA NOGUEIRA |
Monads podem ser vistos com a interface de programação padrão para várias estruturas de dados ou de controle, que são capturados pela classe
Monad do haskell, a qual pertencem todos os monads comuns.
Pode-se dizer que um Monad é como um Monoid das categorias dos Functors, sendo assim:
-o elemento identidade é o return;
-o operador associativo é uma variação de (>>=).
O Applicative pode ser descrito como uma estrutura intermediária entre um functor e monads. Em comparação aos monads, ele não possui todo o
potencial do operador (>>=), porém:
-pode ser usado para resolver encadeamentos com efeito;
-possui mais instâncias;
-as instâncias podem realizar a análises computacionais antes de serem executadas.
|
22 |
GUILHERME FERREIRA GALDINO |
Monad
Monad é uma classe de tipos que possui a seguinte declaração:
class Applicative m => Monad m where
return :: a -> m a -- pure
(>>=) :: m a -> (a -> m b) -> m b
Em que o return encapsula qualquer 'a' em um monad, que antes precisa ser um applicative.
Semelhante ao pure do Applicative.
E o (>>=) semelhante ao (<*>) do Applicative tambem e que nos permite fazer encadeamento de operações.
Quando precisamos executar uma sequência de operações em que uma depende da anterior, monad é uma boa escolha.
Além disso, possui um operador associativo conhecido como peixe ou fish operator
(>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
Semelhante ao uma composição de função, mas para Monads.
Exemplo de Instancia:
instance Monad Maybe where
mx >>= g = case mx of
Nothing -> Nothing
Just x -> g x
Nothing >>= g = Nothing
(Just x) >>= g = g x
Exemplo de Aplicação:
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
Existe um syntax sugar para o operador (>>=) que é o 'do notation':
eval (Div x y) =
do n <- eval x
m <- eval y
maybeDiv n m
Efeitos
Haskell não é cem por cento uma linguagem pura, tendo um limite para o seguintes casos visto nas aulas da semana:
Parcialidade, Não-determinismo e Exceções.
Parcialidade
Alguns casos retorna valores, mas em outros podem gerar erros inesperados ou simplesmente pode não terminar.
Estouro de memoria, loop infinito etc
Utiliza-se o bottom _|_ para lidar com esses situações.
Seria uma terceira de Bool além do True e False.
Nao deterministico
Pode retornar diferentes saídas dependendo de certas condições.
O uso de lista permite enumerar essas possibilidades de saídas, por isso é uma estrutura usada para modelar tal problema.
Outro syntax sugar usado é a compreensão de listas, que seria um syntax sugar do 'do notation'
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
Exceções (Either)
Para lidar com exceções podemos utilizar o Either, o mesmo se aplica para funções parciais.
Assim além de indicar o problema, pode dizer sua causa raiz.
Assim, o Left seria o log do erro e o Right o valor esperado.
Uma instancia de Monad para o caso:
instance Monad (Either a) where
(Left x) >>= f = Left x
(Right x) >>= f = f x
Uma aplicação:
safeDiv :: (Show a, Eq a, Floating a) => a -> a -> Either String a
safeDiv a b
| b == 0 = Left ("Divisao por zero: " ++ show a ++ "/" ++ show b)
| otherwise = Right (a/b)
|
19 |
GaMendes |
|
24 |
HEBER CAMACHO DESTERRO |
Vamos utilizar o conceito de Monads para manter a pureza do Haskell, mas também conseguir realizar
leituras de arquivo, impressão na tela, consulta a banco de dados, entre outras funções.
No Haskell temos um operador chamado Bind que faz o trabalho de vincular o resultado da operação de mx ao argumento da função g
(>>=) :: Monad m => m a -> (a -> m b) -> m b
no nosso exemplo, nosso monad é o Maybe
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
então só precisamos definir uma instancia de Monad para nosso tipo Maybe
O logo do haskell é parecido porque o haskell trouxe como grande benefício o Monad:
operações sequenciais que suportam o efeito (cuidam do efeito pra nós).
Existe um limite até onde nosso programa pode ser puro. De que adianta fazer o calculo e não poder imprimir o resultado na tela?
Temos seguintes casos que precisam de funções impuras:
Parcialidade, que são funções que podem não terminar.
-é feita de forma implícita pelo haskell
ex: data Bool = True | False | _|_
Não-determinismo (lista): funções que podem resultar em multiplas saídas, dependendo de eventos probabilísticos
-todas as possibilidades são colocadas em listas
-combinação de listas através do Monad das listas
Read-only: funções que possuem estados de somente leitura, o banco de dados só pode ser lido, por exemplo
Write-only: funções que imprimem algo na tela ou num arquivo, precisam gerar um lock
Read/Write: combinação dos dois acima
Exceções (Either): tratamento de erros, divisão por zero por ex
--data Either a b = Left a | Right b
IO: entradas e saídas interativas, causam efeito colateral e precisa ser tratado
-list-comprehension é um syntax sugar do do-notation, que é um syntax sugar do bind
|
4 |
HEITOR BELLINI |
-- Monads
A classe Monad é definida pelo operador "bind" e "return", que possibilita "vincular" sequenciamentos de computação, transportando seus efeitos. Vejamos a definição:
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
OBS: SIM! return = pure!!
Para o tipo Maybe, sua instancia de Monad seria:
instance Monad Maybe where
mx >>== g = case mx of
Nothing -> Nothing
Just x -> g x
E para listas:
instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
Uma expressão com o operador bind segue o seguinte padrão:
m1 >>= \x1 ->
m2 >>= \x2 ->
...
mn >>= \xn ->
f x1 x2 ... xn
OBS: Vejam o encadeamento da computação para chegar à aplicação da função!
Temos também um syntatic sugar para Monad, o chamado do-notation:
do x1 <- m1
x2 <- m2
...
xn <- mn
f x1 x2 ... xn
-- Funções de alta ordem para Monads
Temos o Map versão Monad, pela biblioteca Control.Monad:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f [] = return []
mapM f (x:xs) = do y <- f x
ys <- mapM f xs
return (y:ys)
E filter monádico também:
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
filterM p [] = return []
filterM p (x:xs) = do b <- p x
ys <- filter M p xs
return (if b then x:ys else ys)
Uma aplicação de exemplo para a função g abaixo:
g x | x == 0 = Nothing
| even x = Just True
| otherwise = Just False
>>> filterM g [1, 2, 3, 0, 4]
>>> Nothing
|
23 |
HENRIQUE AUGUSTO DE OLIVEIRA |
Os Monads são Applicative Functor com algumas características que os fazem ser únicos e mais poderosos. Uma definição possível para os Monads é que estes são uma generalização de sequenciamento de Computação quando é necessário de funções que geram efeitos colaterais. Os Monads permitem que seja possível gravar informações no Banco de Dados, imprimir informações na tela e outras funções que realizam operações não possíveis com a pureza do Haskell.
Funções impuras são essenciais essenciais, pois nosso programa só tem até um certo nível de pureza. Se não existisse funções impuras, nossa linguagem seria inútil.
A classe Monad possui o operador bind (>>=), cuja assinatura é definida como:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Ou seja, o operador bind pega um objeto de tipo a e devolve um objeto de tipo b. Em linhas gerais, o operador bind garante um encadeamento de computação sequencial para chegar a aplicação de uma função. Pode ser ressaltado que, se uma computação falhar, a falha é alarmada imediatamente e a computação é parada.
Um açúcar sintático para o uso do bind é o "do-notation", que possui a seguinte notação
do x1 <- m1
x2 <- m2
f x1 x2
As funções impuras podem ser utilizadas para Parcialidade, Não-Determinismo, Efeitos Colaterais (Read Only, Write Only, Read/Write), Exceções, Continuações e Entrada e Saída.
É possível cria um Monad do tipo State, que resolve o problema de escrever funções que manipulam estados que são alterados o tempo inteiro. Ou seja, uma determinada entrada produz uma saída, no qual esse estado de saída reflete qualquer alteração no estado da função na execução. Um exemplo seria um gerador de número aleatório. |
25 |
HENRIQUE FANTATO SILVA DE ALBUQUERQUE |
Para resolver problemas onde certas combinações de valores em uma função são proibidas, como
por exemplo, qualquer inteiro dividido por 0 não possui resultado, podemos usar um tipo Maybe.
Porém, ao utilizarmos desse tipo de dados, não podemos mais criar diretamente uma instância de Applicative,
pois essa instância é para computações que tem partes independentes entre si, mas queremos agora algo que
dependa de um resultado anterior. Para isso, utilizamos o operador bind (>>=).
O Monad pode ser visto como um Monoid dos Functors, onde o elemento identidade é o return, e o
operador associativo é uma variação do bind, com a assinatura:
(>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
Basicamente, duas funções do tipo (a -> Monad a) podem ser combinadas gerando uma terceira função
resultante (c -> Monad c).
Além dessa possibilidade de utilizar instâncias de Applicative em tipo de dados com efeitos, o monad
também é aplicado para tratar exceções, não-determinismo, parcialidades, efeitos colaterais e estados!
|
55 |
HENRIQUE MAGRO DE SOUZA |
|
27 |
LEANDRO RIBEIRO DE ALMEIDA |
|
28 |
LEONARDO SANTIAGO HAMPSHIRE |
|
49 |
LOUIS PHILLIPE SARDA DUBOIS |
Monads:
Pode ser visto como um Mooid das categorias dos Functors.
O elemento de unidade é o return (equivalente ao pure) e o operador associativo é uma variação de (>>=).
Quando usamos (>>=) o código só vai prosseguir caso não contenha nenhum erro, no exemplo abaixo, só vamos fazer o eval y se eval x não for Nothing,
o mesmo vale para maybeDiv.
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
Utilisando syntatic sugars, podemos reescrever a o código acima da seguinte maneira:
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = do n <- eval x
m <- eval y
safeDiv n m
Definição da classe Monad
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
return = pure
Monads e efeitos:
Funções impuras necessárias:
- Parcialidade (Valor bottom ⊥)
- Não-determinismo (diferentes saídas dependendo de condições internas e externas)
- Efeitos colaterais: read only, write only, read/write
- Exceções (Either)
- Continuações
- Entrada e saida interativa
Funções de alta ordem: possuem versões para Monads na biblioteca Control.Monad
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f [] = return []
mapM f (x:xs) = do y <- f x
ys <- mapM f xs
return (y:ys) |
31 |
LUCAS DAVID VADILHO |
## Monads
A classe `Monad` é definida pela implementação do operador `bind` de tipo `:t (>>=) :: Monad m => m a -> (a -> m b) -> m b`. Além disso ela necessita que `m` seja `Applicative`, com `return :: a -> m a`, que é o pure.
É um operador que permite a *transferência* do efeito de uma operação.
Para simplificar o padrão `f x >>= \` temos a notação `do` exemplo:
```haskell
eval (Div x y) =
do n <- eval x
m <- eval y
maybeDiv n m
```
## Monads e efeitos
- Parcialidade: `_|_` é adicionado para indicar *erros*
- Não-Determinismo: usando listas?
- Exceções:
- `Maybe`
- `Either` (consegue carregar informações da exceção)
- Esse vídeo devia estar na playlist dessa semana https://www.youtube.com/watch?v=_yKJ2ft9Lg4 |
30 |
LUCAS SILVA AMORIM |
|
32 |
LUCAS YUDI FUKAZAWA CASSIN |
Monad
Operações sequências que transportam o efeito (como um erro por exemplo).
Implementa o "bind" (>>=). Onde (>>=) :: m a -> (a -> m b) -> m b
Implementa o return :: a -> m a (pure de applicative)
Um modo de usar seria: f x >>= \n -> f y >>= \m -> g n m. Vincule o resultado de f de x em n, com o efeito gerado vincule o resultado de f y em m e com o efeito gerado aplique g x y.
Existe um açúcar sintático:
DO notation
do n <- f x
m <- f y
g n m
Evidencia a natureza sequencial do Monad.
Monad são úteis para funções:
Não-determinísticas.
Funções que podem resultar em diferentes saídas a depender de um efeito pré-gerado. Portanto um efeito altera o comportamento dessas funções.
Por exemplo, ao escolher duas cartas de uma baralho a segunda escolha só pode ser do mesmo naipe que a primeira. Nesse caso a segunda escolha depende da primeira, do efeito que ela gerou.
Portanto utiliza-se monad nesse caso.
Exceções.
Encadeia binds, e caso algum elemento retorne um efeito tratado que não prossegue com a computação, não executa o resto do encadeamento de binds.
|
26 |
LUCAS ZOCCHIO |
A class de tipos Monad acrescenta à classe Aplicative a possibilidade de realizar operações cujo resultado de uma próxima operação
depende do efeito da última, tal como a geração de erros ou a leitura de um banco de dados ou arquivo.
Usando instâncias de Monad para tipos já vistos, como Maybe e Either, é possível fazer o tratamento de erros no programa e imprimir mensagens de erro.
O método implementado para intanciar a classe Monad é o "bind" (>>=), cuja assinatura é (>>=) :: m a -> (a -> m b) -> m b,
ou seja, o operador tomar um monoid de um tipo a e uma função do tipo a para monoid de um tipo b e retorna o monoid do tipo b.
Com esse operador, o valor passado à função (a -> m b) é o resultado de m a, portanto o resultado da função depende do efeito de m a.
Um Sintax Sugar pode ser usado para simplificar o uso do (>>=), que é a sintaxe "do", usada como abaixo:
func f x y = do x' <- f x
y' <- f y
return (x, y)
O método return no exemplo acima é um método da classe Monad, mas é idêntico ao pure da classe Applicative, return :: (a -> m a).
As List Comprehensions já antes usadas também são Sintax Sugars, neste caso para a sintaxe "do". |
33 |
LUCCA IANAGUIVARA KISANUCKI |
Bind
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Operador usado para vincular um valor x ao argumento de uma função
Monad
Um Monoid das categorias dos Functors
O elemento identidade é o return
Um operador associativo (>=>), operador peixe (fish operator)
(>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
Expressão do-notation
do x1 <- m1
x2 <- m2
f x1 x2
Facilita a ligibilidade
eval (Div x y) = do n <- eval x
m <- eval y
safeDiv n m
Estado
data State s a = State (s -> (a, s))
Transformador de Estado
REcebe um estado e retorna um valor e um novo estado
Pure
Transformador que não altera o estado
Efeitos Colaterais IO
Funções impuras para alterar o estado atual do sistema
getChar - captura uma char do teclado
putChar - escreve na saida padrão
c <- getChar
putChar c
Temos tambem getLine, putStr e putStrLn
Funções de Alta Ordem em Monads
Disponivel na Biblioteca Control.Monad
mapM, filterM
|
34 |
LUIZ FELIPE LEAL GOMES AZZOLINI |
resumo |
36 |
MARCELO CECILIO FAGUNDES DA SILVA FILHO |
Em haskell a maior parte das expressões são independentes entre si, fazendo com que independente da ordem em que elas são feitas os resultado será igual. Porém em alguns casos a dependência entre funções é importante, por exemplo: ler algo da tela depende que algo tenha sido escrito anteriormente.
Para isso existe os Monads. O Monad é uma classe de tipos que é criada a partir do operador bind (>>=). Este operador recebe uma estrutura do tipo monad com um valor a, uma função que transforma de um valor a para uma estrutura com valor b e retorna uma estrutura com valor b. Ou seja, ele vincula o resultado da computação do primeiro valor ao argumento da função.
Para facilitar a operação existe o operador do que faz o mesmo que o (==>), porém mais fácil de usar e visualizar. Além do bind (>>=) existe o operador return que aplica um valor a em uma estrutura monad, da mesma forma que o pure da classe dos Applicatives. Com isso as funções usando o do ou bind precisam seguir uma ordem e são dependentes uma das outras.
Com isso é possível usar funções que tem um efeito colateral como ler ou escrever na tela. Além de diversas funções que possuem valores diferentes dependendo do resultado de uma função anterior
|
43 |
MARIANA MIWA OKUMA MIYASHIRO |
Monads
- Ao definir tipo para expressões matemáticas e uma função para avaliá-las, temos operações proibidas
- poderia ser tratado com Applicative, mas maybeDiv tem tipo Int -> Int -> Maybe Int
- necessário criar uma função para capturar o padrão de case of
- em Haskell, tem-se um operador bind (>>=):
- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
- Monad = Monoid dos Functors:
- elemento neutro: return
- return :: a -> m a
- operador associativo: variação de bind
- (>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
- syntatic sugar do Monad:
- do-notation:
do x1 <- m1
...
xn <- mn
f x1 ... xn
- instância para Maybe:
instance Monad Maybe where
Nothing >>= _ = Nothing
(Just x)>>= f = f x
- SafeNum
instance Monad SafeNum where
(SafeNum v) >>= f = f v
v >>= _ = boxedCoerce v
Efeitos
- funções impuras são necessárias para:
- parcialidade (pode não terminar)
- não-determinismo (saídas diferentes para condições diferentes)
- tratado com uso de listas:
- instance Monad [] where
xs >>= f = [y | x <- xs, y <- f x]
- compreensão de listas:
pares xs ys = [(x,y) | x <- xs, y <- ys]
== do x <- xs
y <- ys
return (x,y)
- exceções:
- Either generaliza Maybe e permite reportar falhas
- data Either a b = Left a | Right b
- instancia Monad:
instance Monad (Either a) where
(Left x) >>= f = Left x
(Right x) >>= f = f x
|
37 |
MATHEUS ALEXANDRE DE SENA |
|
39 |
MIGUEL MIRA FONSECA |
Uma Monad pode ser entidade como uma generalização de uma sequência de computação
que pode gerar um efeito colateral. Mas diferente de um Applicative uma Monad consegue
resolve problemas de encadeamento. Um exemplo prático seria a continuação do estudo
da classe SafeNum. Podemos criar uma função eval que avalia uma expressão que pode
falar ou não através do uso do tipo Maybe, e uma função vincular que irá propagar
um valor processado de forma correta, mas preservar falhas. Isso é possível através
do operador (>>=) da Monad, por vez chamado de bind.
As vezes a notação pode ficar carregada. Então em Haskell existe o que é chamado
de “do notation” que é um syntax sugar que permite visualizar a computação através
de uma aparência mais procedural. E apesar de Haskell ser conhecida como uma linguagem
funcional pura, na verdade em Haskell também existem funções com efeito colaterais,
porém eles são melhor controlados e canalizados para a função main que é uma
Monad do tipo IO.
Funções impuras são importantes, porque coisas como uso de entrada e saída de dados,
leitura e escrita são importantes para que possamos interagir com o programa. Outras
funções impuras seria funções com componentes probabilísticos ou funções parciais,
que exigem certas pré-condições para que os eu comportamento seja bem definido.
Uma alternativa ao tipo Maybe para tratar erros seria o tipo Either, onde o valor
da esquerda Left irá registrar o erro, e o valor da direita Right irá guardar os
valores de retorno. Com isso podemos não somente saber quando a função irá dar errado,
mas o porque ela deu errado no caso. O tipo Either então funciona como o construto
de exceção em outras linguagens. E ambos são Monads. |
41 |
NATALIA LEITE VARES DE SOUZA |
MONADS
Monads são extensões naturais de applicative functors.
A função principal do Monad é dada por:
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
Essa função captura o padrão de ‘case of’, sendo conhecida também como ‘bind’
MONOID DE MONADS
Assim como functors tem o tipo de classe Functor e applicative functors tem o tipo de classe Applicative, os monads tem tipo de classe Monad.
Em teoria das categorias um Monad pode ser visto como um Monoid das categorias dos Functors, onde o elemento identidade é o ‘return’ e o operador associativo é uma variação de (>>=) com a assinatura:
(>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)
O operador (>=>) garante que se uma computação falhar, ela para imediatamente e reporta a falha.
MONADS E EFEITOS
Mesmo que o Haskell seja considerada uma linguagem puramente funcional, existe uma limite do quão puro o programa pode ser.
As funções impuras são importantes para diversas situações:
- Parcialidade: como quando temos uma função que pode não terminar
- Não-determinismo: como quando uma função pode retornar diferentes saídas dependendo de certas condições
- Exceções (função Either): como quando lidamos com funções parciais ou que geram exceções e queremos identificar qual foi o problema
- Efeitos colaterais: Read only, Write only, Read/Write
- Entrada e saída iterativa: pois alteram o estado atual do sistema.
FUNÇÕES DE ALTA ORDEM PARA MONADS
As funções de alta ordem possuem versões para Monads na biblioteca específica Control.Monad
Temos funções como map (mapM) e filter (filterM), onde a principal diferença é:
- filter seleciona elementos de uma lista
- filterM seleciona possíveis eventos de uma sequência de computações
|
40 |
NATHALIA CORREA DOS SANTOS |
Monads
Os monads permite uma generalização de funções para que possamos lidar com os efeitos colaterais.
Podemos utilizar o operador bind (>>=) quando eu necessito realizar a seguinte operação: m a -> (a -> m b) -> m b.
O conceito de monads é a grande "sacada" da linguagem Haskell, pois é ela que cuida dos efeitos colaterais para a gente.
A classe monad depende que também seja um applicative, pois além do bind ele possui o operador return.
O que diferencia o monad de um applicative é que o applicative é independente, não dependendo de uma sequência. Já o monad ele é um applicative considerando
a sequência.
A função Either pode ser utilizada para gerarmos logs na execução de funções, facilitando assim o debug e entendimento do código desenvolvido.
O operador >=> realiza a composição de monads.
|
48 |
PAULO GABRIEL MASSA |
|
44 |
PAULO HENRIQUE EIJI HAYASHIDA |
|
47 |
PEDRO ANTUNES NEGRÃO |
Na semana 07 foi apresentado o significado de Monads e algumas de suas aplicações. Por ser um conteúdo bastante extenso, ele foi dividido em duas partes e nessa semana foram disponibilizados 4 video aulas (11.1 até 11.4).
Se uma linguagem de programação puramente funcional não tivesse recursos para por exemplo, imprimir informações na tela, capturar inputs do teclado, gravar informações em um arquivo, ler registros de um banco de dados, entre outros, ela seria inútil. Por isso o Haskell apresenta um conceito chamado de Monads que diversas linguagens de programação multiparadigmas implementaram em seus códigos.
A classe Monads pode ser utilizada para o encadeamento das operações computacionais (transportando o efeito delas), já que o Applicative não consegue realizá-lo. Essa classe possui duas funções, uma é o return que nada mais é do que a função pure do Applicative, ou seja, ele pega um valor de a e retorna um 'm' de a. A outra função é o operador bind denotado por '>>=' (que deu origem ao logo do Haskell) no qual ele pega algum valor que está 'encapsulado' (i.e. Just 5, [5], etc.) e atribui o valor puro em uma função anônima (função lambda). Exemplo de implementação:
eval (Div x y) =
eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
É possível utilizar um açúcar sintático denotado pela palavra reservada 'do':
eval (Div x y) =
do
n <- eval x
m <- eval y
maybeDiv n m
Na segunda video-aula foi ensinado como criar uma instância da classe Monad para o tipo SafeNum, que foi criado em aulas anteriores. Já no terceiro vídeo foi visto alguns benefícios de linguagens impuras como IO, Parcialidade, Não-Determinismo (Lista) e como o Haskell contorna cada um desses casos. Por fim, foi explicado como utilizar um Monad do tipo Either, que pode ser utilizado para o tratamento de exceções e logs. |
45 |
PEDRO BRAGA DOS SANTOS BACELLAR |
|
46 |
PEDRO MACHADO NERY DOS SANTOS |
Monads se relacionam a realização de operações sequencialmente tratando de efeitos. São definidas pelo operador bind (>>=) que explica como realizar tal tratamento. Applicatives têm uma aplicação similar, mas exigem que efeitos das computações sejam independentes entre si, o que não é sempre o caso. Pela similaridade, no entanto, o operador pure dos Applicatives faz parte da definição da classe Monad junto ao bind, mas com o nome de return.
eval::Expr -> Maybe Int
eval(Div x y) =
do n <- eval x --realiza eval de x e vincula o resultado a m se diferente de Nothing
m <- eval y
maybeDiv n m --trata os efeitos pelas variáveis vinculadas m e n
Monads podem ser vistas como Monoid de Functors, sendo return o elemento identidade e ((>=>) ::Monad m=> (a -> m b) -> (b -> m c) -> (a -> m c)) o operador associativo. Assim Monads associam funções para gerar uma terceira e possuem um elemento neutro.
O tratamento mostrado acima permite que Monads tenham controle da falha de qualquer operação intermediária ao tentar fazer o Bind, permitindo combiná-las num resultado final de forma mais clara. Isso é aplicado ao caso SafeNum visto em aula, além do caso de MaybeDiv acima, para tratamento de erro (de forma alternativa a blocos try/catch de outras linguagens).
Monads também podem ser usadas para introduzir não-determinismo e tratar effeitos colaterais em funções de entrada e saída, além de tornar mais clara a aplicação parcial de funções. |
53 |
PEDRO REGIO SHOJI |
|
50 |
PIETRO DI CONSOLO GREGORIO |
A classe Monad permite uma generalização de sequenciamento de computação quando é preciso de funções que gerem efeitos colaterais, ou seja, implementa o conceito de operações sequenciais que transportam o efeito, além disso um Monad pode ser visto como um Monoid das categorias dos Functors. Essa classe é definida pelo operador bind (>>=) e o elemento identidade é o return.
Um syntactic sugar para as expressões construídas com o operador bind é a notação chamada do-notation, simplificando a forma de escrita da operação e que evidencia o natureza sequencial dela. A classe Monad depende também que ele seja um Applicative, sendo o pure idêntico ao return, mudando apenas o contexto. É possível criar uma instância de Monad para SafeNum, o que possibilita repassar possíveis erros durante as operações.
A parcialidade é quando funções podem ou não terminar, o Haskell trata esses casos através do bottom (_|_), que sinaliza algo que pode falhar ou não retornar. O não-determinismo é quando uma função pode retornar diferentes saídas dependendo de certas condições. A implementação de Monads para listas é a implementação de combinação de duas ou mais listas. O list comprehension é um syntactic sugar do do-notation.
O uso do Maybe para lidar com funções parciais ou que geram exceções apenas indica que aconteceu um problema, já a utilização do Either permite reportar o ponto onde ocorreu a falha. |
10 |
RAFAEL BRUNO FERREIRA FIGUEIREDO |
Monads:
São utilizados para verificar passo a passo os resultados de sequencias de execução. Por exemplo, uma função passa por varios possíveis pontos de falha, como divisão por zero, e os monads são atalhos para tratar as possíveis falhas. Ela "cuida do efeito".
O operador bind (>>=) é uma função da classe monad que faz essa "verificação".
(>>=) :: m a -> (a -> m b) -> mb
Ex:
eval x >>= \n (se eval x for nothing retorna nothing e para execução. Se for Just, segue vinculando x em n)
eval y >>= \m
maybeDiv n m (caso passem 2 Just realiza o maybeDiv)
Do notation:
do
n <- eval x
m <- eval y
maybeDiv n m
Monads Lista: Modo de capturar eventos anteriores da lista. O list comprehension funciona baseado no conceito de monad, já que "corre" uma lista agindo sobre ela.
Em linhas gerais é uma forma de "estruturar" passos de código em haskell, uma ferramenta que ajuda a manter controle do código em computações probabilísticas. Em programações estruturadas isso é feito analisando os resultados das execuções passo a passo, no haskell (e outras linguagens funcionais) isso é realizado com ajuda dos monads. |
51 |
RAFAEL PAUWELS DE MACEDO |
Nessa sequência de vídeos aprendemos sobre Monads, primeiro vimos implementação de um tipo chamado Expr que serviu como motivação para a utilização de Monads quando temos situações que envolvem muita repetição.
Dessa forma vimos como poderiamos melhorar nosso código usando o operador >>== (bind), que é o método que precisamos definir ao criar uma nova instância de Monad. Importante notar que além do bind é preciso que também exista uma instância de Applicative.
Como o uso do operador bind é tão comum dentro do Haskell existe um syntax sugar chamado de "do notation" que nos permite criar estruturas sequenciais do tipo:
do n <- eval x
m <- eval y
maybeDiv n m
Ao invés da estrutura com bind:
eval x >>== \n ->
eval y >>== \m ->
maybeDiv n m
Em seguida voltamos ao exemplo do SafeNum para ver em prática um exemplo de utilização de um Monad.
O próximo assunto foi sobre a aplicação de monad em listas, criamos um tipo Dado e um método que gera uma tupla com todos os possíveis valores de dois dados e vimos como utilizar um Monod para que um segundo valor tenha dependência de um valor calculado anteriormente.
Além do syntax sugar "do notation" vimos também que as list comprehension também são syntax sugar de Monads.
Por fim vimos o Monad Either, que nos possibilita construir formas mais completas de tratar erros. O Either tem a estrutura
Either a b = Left a | Right b
Sendo o Left uma possível mensagem de erro e o Right o valor caso tudo corra bem. |
52 |
RAPHAEL RAMOS DA SILVA |
------------------------------------------------------- Monads ---------------------------------------------------
- Applicative não se aplica para operações sequênciadas com efeito colateral dependentes entre si.
- O Monad veio para corrigir isso, permitindo uma generalização de sequenciamento da computação quando precisamos
utilizar funções que geram efeitos colaterais (alteram o estado global do sistema).
----------------------------------------------------- Exemplo (Expr) ----------------------------------------------
(definindo o tipo) data Expr = Val Int | Add Expr Expr | Sub Expr Expr | Mul Expr Expr | Div Expr Expr
(função para calcular Expr) eval :: Expr -> Maybe Int
eval (Div x y) =
case eval x of
Nothing -> Nothing (se x for Nothing, já devolva Nothing e dispense a avaliação de y)
Just n -> case eval y of
Nothing -> Nothing
Just m -> maybeDiv n m
- O uso de applicative não funciona no exemplo acima (por conta do encademento).
A função "vincular" abaixo poderia ser utilizada para o caso acima
vincular :: Maybe a -> (a -> Maybe b) -> Maybe b
vincular mx g = case mx of
Nothing -> Nothing
Just x -> g x
- Essa função vincular já existe no Haskell (operador bind) - da classe Monad (definição abaixo)
class Applicate m => Monad m where
return :: a -> m a (como se fosse o "pure" de Applicative)
(>>=) :: m a -> (a -> m b) -> m b (operador bind)
---------------------------------------- Resolvendo o Exemplo (Expr) com Monad ----------------------------------
instance Monad Maybe where
mx >>= g = case mx of
Nothing -> Nothing
Just x -> g x
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
(syntax sugar do)
eval (Div x y) =
do n <- eval x
m <- eval y
maybeDiv n m
------------------------ Desafios em manter a pureza na programação (uso de Monads ajuda) ----------------------
- Parcialidade: funções que podem não ter fim (Ex.: função head em lista vazia)
- Não-Determinismo: funções que podem ter múltiplas saídas (dependência de resultados probabilísticos)
- Exceções (Either)
- Read-only / Write-only / Read/Write / IO - (conteúdo da próxima semana)
|
29 |
RENAN FERREIRA LIMA |
Nessa semana o tema foi a classe Monad, a qual possui uma função em formato de operador, o bind (>>=). O bind devolve um m b, se tiver como entrada um monad m e uma função de a para m b, um syntax sugar para o bind é o do notation, que simplifica a forma de declaração do monad, evidenciando sua natureza sequencial.
Pode-se destacar que o monad é um applicative quando se considera a sequência, um outro ponto relevante, é que é possível implementar o bind usando o pattern matching, por exemplo, para o maybe.
Aplicando monads em listas, podemos citar o list comprehension que é um syntax sugar para o do notation, verificando elemento a elemento de forma sequencial na lista, conforme já apresentado no início do curso.
Voltando ao SafeNum é possível implementar uma instância usando monads, de modo que se a entrada for um SafeNum envolto de outro SafeNum, o retorno será a aplicação direta de f no primeiro SafeNum. Contudo, caso o SafeNum não esteja envolto por outro SafeNum, é possível aplicar o boxedCoerce para repassar o erro adiante, nesse caso não é necessário aplicar uma função. Também é possível usar o do notation associado a operações como safeDiv, safeAdd, entre outras.
Para o tratamento de exceções podemos destacar a instância EIther, que é capaz de controlar exceções e manter informações da exceção que foi gerada, diferente do Maybe que só apresentava a exceção. Assim, podemos criar um safeDiv por exemplo, e assim detalhar o log em caso de erro.
|
54 |
RENAN GONCALVES MIRANDA |
|
57 |
VINICIUS DE OLIVEIRA CAMPOS DOS REIS |
|
0 |
VITOR MARINI BLASELBAUER |
|
58 |
VITOR RUBENS SNIQUER LEAO MARTINS |
|
56 |
VITTORIA ARIEL DOS SANTOS BOROTTO |
=> Monads
Como estudado anteriormente o Applicative é para sequências de computações que podem
ter efeitos mas que são independentes entre si
Mas agora queremos uma sequência de computações com efeito mas que uma computação dependa da anterior.
No exemplo abaixo:
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = case eval x of
Nothing -> Nothing
Just n -> case eval y of
Nothing -> Nothing
Just m -> maybeDiv n m
Porem queremos uma funcao para capturar o padrao de case of, portanto:
vincular :: Maybe a -> (a -> Maybe b) -> Maybe b
vincular mx g = case mx of
Nothing -> Nothing
Just x -> g x
O haskell tem um operador pra auxilixar nisso chamado bind >>=
Um monad pode ser enxergado como Monoid das categorias dos functors,
o qual o elemento identidade é o return e o operador associativo >>=
Dessa maneira duas funcoes transformam um valor em um Monad e podem formar outra funçao
Dessa forma reescrevemos eval:
eval :: Expr -> Maybe Int
eval (Val n) = Just n
eval (Div x y) = eval x >>= \n ->
eval y >>= \m ->
maybeDiv n m
O monad permite que indique um encadeamento de computação sequencial para chegar a uma aplicação de função.
Garantindo que se uma computação falhar, ela para imediatamente e reporta a falha
Além do operador bind ela redefine a função pure com o nome de return
Basicamente voce aplica a funcao que retorna um valor em contexto usando >>=
=> Monads e efeitos
Mesmo o haskell sendo conhecido como puramente funcional, existe um limite,
sendo necessarias funcoes impuras tbm para parcialidade, nao-determinismo, efeitos colateriais,
excecoes, continuacoes, entrada e saida interativa
parcialidade: funcao que pode nao terminar: retorna True, False ou _|_
nao-determinismo: uma função pode retornar diferentes saídas dependendo de certas condições internas ou externas
entre outros cenarios citados anteriormente |
59 |
WESLEY AXEL DE BARROS |
Para esta semana 07, tivemos um topico muito importante para o estudo de Haskell na disciplina de Paradigmas de Programação.
Estudamos a primeira parte do conceito de Monads, que são uma extensão dos functors, aonde se utilizando do operador associativo bind "(>>=)", em um "x" de uma função "a", e
você possui uma função "a" para um "x" de "b", você tem como retorno uma função "x" de "b". Ou seja, transformando duas funções com valores puros em uma terceira função.
Verificamos como aplicar a expressão de monads com o "do-notation", que é um syntatic sugar do operador bind, tendo como a função pure a função "return".
Implementamos o conceito de Monads nas aplicações do tipo Safenum, aonde o operador bind tem como retorno um tipo do Safenum dizendo se a operação extrapolou os limites numericos ou
se por exemplo acabou fazendo uma divisão por zero.
E começamos a ver como o conceito de Monads é aplicado na linguagem Haskell para se obter funções impuras, para se obter por exemplo, funções com parcialidade, aonde se obtem um valor que não
tem fim; Funções com não determinismo, aonde as suas saidas/resultados podem ter valores diferentes com base de certas condições internas ou externas; E também a função Either, que é um monad,
que pode ser utilizado para fazer o tratamento de exceções em funções com valores que podem não serem exatos/corretos.
|
60 |
WILLIAM SENA SILVA |
|
14 |
francesquini |
|