~misterio/veraoPFPA-Listas

13cd1d0397277cdfe20eca6ab23f31f5206be82e — Gabriel Fontes 5 months ago 6412b58
finaliza pdf da lista
1 files changed, 133 insertions(+), 8 deletions(-)

M lista.md
M lista.md => lista.md +133 -8
@@ 8,7 8,7 @@ main = print $ \

Gabriel Silva Fontes

## 1. Construa o _list comprehension_ que gere:
## 1) Construa o _list comprehension_ que gere:

### a) [0,5,10,15,20,25,30,35,40,45,50]



@@ 54,8 54,7 @@ Gabriel Silva Fontes
    [ (x, y) | x <- ['a'..'h'], y <- [1..8] ]
```


## 2. Crie as funções da forma como solicitado:
## 2) Crie as funções da forma como solicitado:


### a) Crie uma função recursiva que verifique se um elemento esta presente em uma lista, deixe explicita a assinatura da função


@@ 122,7 121,7 @@ main = do
```
-->

## 3. Siga as instruções abaixo na sequência
## 3) Siga as instruções abaixo na sequência:

### a) Crie um tipo Cor que possua um _value constructor_ de mesmo nome que carregue 3 valores do tipo Int.



@@ 132,7 131,7 @@ main = do
data Cor a = Cor a a a
```

### b) Cada um dos valores do tipo Int são relativos aos valores RGB (red, green, blue), pra cada um desses valores crie (manualmente) uma função de projeção, o nome das funções devem ser red, green e blue, respectvamente para cada um dos valores do tipo Int. 
### b) Cada um dos valores do tipo Int são relativos aos valores RGB (red, green, blue), pra cada um desses valores crie (manualmente) uma função de projeção

*Solução*:
<!-- name: 3-b require: 3-a -->


@@ 155,7 154,7 @@ blue (Cor _ _ b) = b
data Cor a = Cor { red::a, green::a, blue::a }
```

### d) Crie uma função com o nome somaCor, que combine dois valores do tipo Cor, de forma que o resultado deve ser um novo valor, também do tipo Cor, onde os valores relativos ao RGB (red, green e blue), são relativos a soma dos valores RGB dos parâmetros da função, respectivamente. Caso algum valor relativo relativo ao valores RGB do resultado seja maior 
### d) Crie uma função com o nome somaCor, que combine dois valores do tipo Cor

*Solução*:
<!-- name: 3-d require: 3-c -->


@@ 167,7 166,7 @@ somaCor a b =
        canal f = min 255 $ (f a)+(f b)
```

### e) Crie um operador <+> que faça a mesma coisa que a função somaCor, utilize-se do conceito de currying para definir o operador. (Os símbolos de maior e menor fazem parte do operador)
### e) Crie um operador <+> que faça a mesma coisa que a função somaCor, utilize-se do conceito de currying para definir o operador

*Solução*:
<!-- name: 3-e require: 3-d -->


@@ 176,7 175,7 @@ somaCor a b =
(<+>) = somaCor
```

### f) Crie uma instância de Monoid para o tipo Cor, onde a operação bínaria seja o operador <+> e o elemento nêutro seja um valor do tipo Cor que contem os valores RGB como 0.
### f) Crie uma instância de Monoid para o tipo Cor, onde a operação bínaria seja o operador <+> e o elemento neutro seja um valor do tipo Cor que contem os valores RGB como 0.

*Solução*:
<!-- name: 3-f require: 3-e -->


@@ 216,3 215,129 @@ instance Applicative Cofre where
    pure x = Cofre [x]
    (Cofre f) <*> (Cofre x) = Cofre $ f <*> x
```

## 5) Siga as instruções abaixo na sequência:

### a) Crie o tipo `Automovel` que possua dois _value constructors_, um para representar o carro, e o outro para representar a moto

*Solução*:
<!-- name: 5-a -->
```haskell
data Automovel = Carro | Moto
```

### b) Crie um tipo `Veiculo` que possua um _value constructor_ de mesmo nome que carregue 2 valores, o primeiro de nome `automovel` do tipo `Automovel`, o segundo de nome `placa` do tipo String.

*Solução*:
<!-- name: 5-b require: 5-a -->
```haskell
data Veiculo = Veiculo {
    automovel :: Automovel,
    placa :: String
}
```

### c) Crie um _typeclass_ `EhCarro`, para tipos de _kind_ *, que possua uma função com nome `ehCarro` que receba um valor do tipo do _type parameter_ do _typeclass_, e retorne um valor do tipo `Bool` informando se é um carro.

*Solução*:
<!-- name: 5-c require: 5-b -->
```haskell
class EhCarro a where
    ehCarro :: a -> Bool
```

### d) Crie uma instância de `EhCarro` para o tipo `Veiculo`

*Solução*:
<!-- name: 5-d require: 5-c -->
```haskell
instance EhCarro Automovel where
    ehCarro Carro = True
    ehCarro Moto = False

instance EhCarro Veiculo where
    ehCarro = ehCarro . automovel
```

### e) Crie uma instância de `EhCarro` para o tipo `Int` (Nenhum número é um carro)

*Solução*:
<!-- name: 5-e require: 5-d -->
```haskell
instance EhCarro Int where
    ehCarro _ = False
```

## 6) Seguindo os axiomas de Peano:

### a) Crie o tipo `Natural`, que possua dois _value constructors_, um para representar o valor zero, e outro para representar a sucessão de um valor do tipo `Natural`

*Soluçao*:
<!-- name: 6-a -->
```haskell
data Natural = Zero | Succ Natural
```

### b) Crie uma função `somaNatural`, que receba dois parâmetros do tipo Natural que você criou, e retorne um valor do tipo natural que seja a soma dos dois parâmetros

*Solução*:
<!-- name: 6-b require: 6-a -->
```haskell
somaNatural :: Natural -> Natural -> Natural
somaNatural x Zero = x
somaNatural x (Succ y) = Succ $ somaNatural x y
```

### c) Crie uma função que converta `Natural` para `Int`

*Solução*:
<!-- name: 6-c require: 6-b -->
```haskell
naturalParaInt :: Natural -> Int
naturalParaInt Zero = 0
naturalParaInt (Succ x) = 1 + naturalParaInt x

-- De bônus, uma pra fazer o inverso disso
intParaNatural :: Int -> Maybe Natural
intParaNatural 0 = Just Zero
intParaNatural x
    | x < 0 = Nothing
    | otherwise = fmap Succ $ intParaNatural (x-1)
```

## 7) Crie uma função que receba 3 parâmetros, sendo eles duas funções (referenciadas aqui no enunciado como f e g) e um valor (referenciado aqui no enunciado como x), e retorne uma tupla de duas posições contendo na primeira posição o resultado de f composta em g aplicado em x e na segunda o resultado de g composta em f aplicado em x. Construa a função da forma mais genérica que for possível de criar uma função com essas caracteristicas e deixe explicita a assinatura da função. Faça uma breve explicação sobre a forma como vc pensou para criar essa função.

*Solução*:
```haskell
funcao :: (a -> a) -> (a -> a) -> a -> (a, a)
funcao f g x = (f . g $ x, g . f $ x)
```

*Explicação*:

Vamos nomear os tipos. Considere que x é do tipo `a`, f é do tipo `(b -> c)`, e g é do tipo `(d -> e)`.

Por causa do `f . g $ x`, temos que `d = a` (entrada de g tem o mesmo tipo que x), e que `e = b` (saída de g tem o mesmo tipo que a entrada de f). Assim podemos afirmar que g é do tipo `(a -> b)`.

Por causa do `g . f $ x`, temos que `b = a` (entrada de f tem o mesmo tipo que x), e que `c = d` (saída de f tem o mesmo tipo que a entrada de g). Assim, unido com o constatado acima, sabemos que `c = a` e podemos dizer que f tem tipo `(a -> a)` e g tem o mesmo tipo `(a -> a)`.

Portanto, a forma mais genérica possível tem como restrição que ambas as funções recebam e retornem o mesmo tipo que x possui. Existindo, então, apenas um _type parameter_ na assinatura da função.


\newpage
## 8) Crie um tipo `JoKenPo` que possua três _value constructors_, representando as jogadas pedra, papel, tesoura. Crie um tipo `Resultado` que possua três _value constructors_, representando os resultados da vitória do jogador 1, a vitória do jogador 2, e o empate. Cria uma função `jogar`, que recebe duas jogadas do tipo `JoKenPo`, retorne o resultado do tipo `Resultado`.
*Solução*:
```haskell
data JoKenPo = Pedra | Papel | Tesoura
    deriving (Ord, Eq)

data Resultado = Vitoria1 | Vitoria2 | Empate

jogar :: JoKenPo -> JoKenPo -> Resultado
jogar Pedra Tesoura = Vitoria1
jogar Tesoura Pedra = Vitoria2
jogar x y
    | x == y = Empate
    | x > y = Vitoria1
    | x < y = Vitoria2
```