Jump to content
crislanio_macedo

Erro ao tentar fazer uma função que utiliza Maybe

Recommended Posts

crislanio_macedo

Olá senhores, estou a ter grandes problemas na construção de uma função rotina' que recebe uma Barra e uma lista de pousos devolve uma Maybe Barra.

Vejamos abaixo o código completo.


type Passaros = Int
type Barra = (Passaros, Passaros)

data Pos = Esq | Dir deriving (Eq, Show)
type Pouso =(Pos, Passaros)

pousoEsq :: Passaros -> Barra -> Maybe Barra
pousoEsq n (esq, dir)
| abs ((esq+n) - dir) < 4 = Just (esq +n, dir)
| otherwise = Nothing

pousoDir :: Passaros -> Barra -> Maybe Barra
pousoDir n (esq, dir)
  | abs (esq -(dir+n)) < 4 = Just (esq, dir+n)
  | otherwise = Nothing

-- return (0,0) >>= pousoDir 2 >>= pousoEsq 2 >>= pousoDir 2
-- return Just(2,4)
--return (0,0) >>= pousoEsq 1 >>= pousoDir 4 >>= pousoEsq (-1) >>= pousoDir (-2)
--return Nothing
rotina :: Maybe Barra
rotina = case pousoEsq 1 (0,0) of
Nothing -> Nothing
Just barra1 -> case pousoDir 4 barra1 of
	Nothing -> Nothing
   Just barra2 -> case pousoEsq 2 barra2 of
		Nothing -> Nothing
		Just barra3 -> pousoEsq 1 barra3


b1 = (0,0) :: Barra
p1 = (Esq, 2) :: Pouso
p2 = (Dir, 4) :: Pouso
sq = [p1, p2]

--rotina1 :: Barra -> [Pouso] -> Maybe Barra
-- rotina1 b1 sq == Just (2, 4)
rotina1 b1 [] = return b1
rotina1 b1 (x:xs) = do {
y<- if fst x == Esq then pousoEsq b1 (snd x) else pousoDir b1 (snd x);
return rotina1 y xs ;
}

Me ajudem nessa solução que para mim está a ser complicada, att.

Erro:


Couldn't match type `[(Pos, Barra)] -> Maybe Passaros'
with `Maybe Passaros'
Expected type: Barra -> [(Pos, Barra)] -> Maybe Passaros
Actual type: Barra
-> Passaros -> [(Pos, Barra)] -> Maybe Passaros
The function `return' is applied to three arguments,
but its type `(Passaros -> [(Pos, Barra)] -> Maybe Passaros)
-> Barra -> Passaros -> [(Pos, Barra)] -> Maybe Passaros'
has only four
In a stmt of a 'do' block: return rotina1 y xs
In the expression:
do { y <- if fst x == Esq then
pousoEsq b1 (snd x)
else
pousoDir b1 (snd x);
return rotina1 y xs }
Failed, modules loaded: none.

Edited by crislanio_macedo

Share this post


Link to post
Share on other sites
thoga31

Definiste que b1 é do tipo Barra, mas na função rotina1 passas b1 como primeiro argumento das funções pousoEsq e pousoDir. Ora, o primeiro argumento de ambas estas funções é Passaros.


Knowledge is free!

Share this post


Link to post
Share on other sites
crislanio_macedo


b1 = (0,0) :: Barra
p1 = (Esq, 2) :: Pouso
p2 = (Dir, 4) :: Pouso
sq = [p1, p2]

rotina1 :: Barra -> [Pouso] -> Maybe Barra
-- rotina1 b1 sq == Just (2, 4)

rotina1 b1 [] = return b1
rotina1 b1 (x:xs) = do {
   y<- if fst x == Esq then pousoEsq (snd x) b1 else pousoDir (snd x) b1;
   return rotina1 y xs ;
}

Em rotina1 o return y xs. está a dar erros,


Couldn't match type `[Pouso] -> Maybe Barra' with `Maybe Barra'
Expected type: Barra -> [Pouso] -> Maybe Barra
Actual type: Barra -> Barra -> [Pouso] -> Maybe Barra
The function `return' is applied to three arguments,
but its type `(Barra -> [Pouso] -> Maybe Barra)
-> Barra -> Barra -> [Pouso] -> Maybe Barra'
has only four
In a stmt of a 'do' block: return rotina1 y xs
In the expression:
do { y <- if fst x == Esq then
pousoEsq (snd x) b1
else
pousoDir (snd x) b1;
return rotina1 y xs }

Share this post


Link to post
Share on other sites
crislanio_macedo

Code.


type Passaros = Int
type Barra = (Passaros, Passaros)

data Pos = Esq | Dir deriving (Eq, Show)
type Pouso =(Pos, Passaros)

pousoEsq :: Passaros -> Barra -> Maybe Barra
pousoEsq n (esq, dir)
| abs ((esq+n) - dir) < 4 = Just (esq +n, dir)
| otherwise = Nothing

pousoDir :: Passaros -> Barra -> Maybe Barra
pousoDir n (esq, dir)
| abs (esq -(dir+n)) < 4 = Just (esq, dir+n)
| otherwise = Nothing

-- return (0,0) >>= pousoDir 2 >>= pousoEsq 2 >>= pousoDir 2
-- return Just(2,4)
--return (0,0) >>= pousoEsq 1 >>= pousoDir 4 >>= pousoEsq (-1) >>= pousoDir (-2)
--return Nothing
rotina :: Maybe Barra
rotina = case pousoEsq 1 (0,0) of
Nothing -> Nothing
Just barra1 -> case pousoDir 4 barra1 of
Nothing -> Nothing
Just barra2 -> case pousoEsq 2 barra2 of
Nothing -> Nothing
Just barra3 -> pousoEsq 1 barra3


b1 = (0,0) :: Barra
p1 = (Esq, 2) :: Pouso
p2 = (Dir, 4) :: Pouso
sq = [p1, p2]

rotina1 :: Barra -> [Pouso] -> Maybe Barra
-- rotina1 b1 sq == Just (2, 4)

rotina1 b1 [] = return b1
rotina1 b1 (x:xs) = do {
y<- if fst x == Esq then pousoEsq (snd x) b1 else pousoDir (snd x) b1;
return rotina1 y xs ;
}

Error.

Prelude>
Prelude> :l rotinaP.hs
[1 of 1] Compiling Main ( rotinaP.hs, interpreted )

rotinaP.hs:34:6:
Couldn't match expected type `t0
-> Barra -> [Pouso] -> Maybe Barra'
with actual type `[Pouso]'
The function `[p1, p2]' is applied to one argument,
but its type `[Pouso]' has none
In the expression:
[p1, p2] rotina1 :: Barra -> [Pouso] -> Maybe Barra
In an equation for `sq':
sq = [p1, p2] rotina1 :: Barra -> [Pouso] -> Maybe Barra

rotinaP.hs:42:9:
Couldn't match type `[(Pos, Passaros)] -> Maybe Barra'
with `Maybe Barra'
Expected type: Barra -> [(Pos, Passaros)] -> Maybe Barra
Actual type: Barra -> Barra -> [(Pos, Passaros)] -> Maybe Barra
The function `return' is applied to three arguments,
but its type `(Barra -> [(Pos, Passaros)] -> Maybe Barra)
-> Barra -> Barra -> [(Pos, Passaros)] -> Maybe Barra'
has only four
In a stmt of a 'do' block: return rotina1 y xs
In the expression:
do { y <- if fst x == Esq then
pousoEsq (snd x) b1
else
pousoDir (snd x) b1;
return rotina1 y xs }
Failed, modules loaded: none.

Share this post


Link to post
Share on other sites
pwseo

crislanio_macedo,

Vou fazer mais uma advertência relativamente aos teus posts: é suposto deixares clara a tua dúvida e que tentativas já fizeste para resolver o problema com que te deparaste. Posts simplesmente com um bloco de código e o erro emitido pelo compilador são um convite para que ninguém te responda e, em casos mais graves e reincidentes, são candidatos a acção por parte da equipa de moderação.

Vamos começar pelo bloco de código onde defines rotina. Devido à forma como os Monads são implementados em Haskell, o operador (>>=) funciona de forma a interromper uma cadeia de computações logo que uma delas falhe:

(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing  >>= _ = Nothing
(Just x) >>= f = f x

Como podes ver (mesmo ignorando a assinatura), quando (>>=) recebe Nothing como primeiro argumento (ie. quando a primeira computação falha), o seu segundo argumento é ignorado e devolve-se logo Nothing.

Quando utilizas um bloco do em Haskell estás implicitamente a utilizar o operador (>>=) entre cada linha de código (se quiseres saber mais poderás perguntar ou ler quando quiseres).

Em suma, estes mecanismos permitem simplificar o teu código para o seguinte, uma vez que todo o processo de interromper a computação se aparecer um Nothing faz parte do próprio operador (>>=):

rotina :: Maybe Barra
rotina = do
 barra1 <- return (0,0)
 barra2 <- pousoEsq 1 barra1
 barra3 <- pousoDir 4 barra2
 barra4 <- pousoEsq 2 barra3
 pousoEsq 1 barra4

 -- o resultado será Just (4,4)

E agora podemos passar para a tua função rotina1, que também beneficiaria de uma limpeza.

Em primeiro lugar, por que motivo utilizas {} e ; quando escreves blocos do? Além do código ficar mais feio (sem qualquer sombra de dúvida), também é muito mais propício a erros.

Vamos reformulá-lo:

rotina1 :: Barra -> [Pouso] -> Maybe Barra
rotina1 b1 [] = return b1
rotina1 b1 (x:xs) = do
 y <- if fst x == Esq then pousoEsq (snd x) b1
                      else pousoDir (snd x) b1
 return rotina1 y xs

O erro que o compilador emite diz respeito ao facto de que não podes utilizar return nessa linha.

Se rotina1 já devolve um valor do tipo Maybe Barra, então não podes fazer return desse valor, pois estarias a criar algo como Maybe (Maybe Barra).

O correcto seria, portanto:

rotina1 :: Barra -> [Pouso] -> Maybe Barra
rotina1 b1 [] = return b1
rotina1 b1 (x:xs) = do
 y <- if fst x == Esq then pousoEsq (snd x) b1
                      else pousoDir (snd x) b1
 rotina1 y xs

E já agora:

*Main> rotina1 (0,0) [(Esq, 1), (Dir, 4), (Esq, 2), (Esq, 1)]
Just (4,4)

Verifica lá se era isso que pretendias ou não (e se não for, cá estamos para te esclarecer, desde que te expliques devidamente).

  • Vote 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.