• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Baderous

Conflito entre Integral e Floating

5 mensagens neste tópico

O uso da função mod e sqrt com o mesmo argumento gera um conflito devido aos seus tipos:

mod :: (Integral a) => a -> a -> a
sqrt :: (Floating a) => a -> a

Como posso resolver isto? (preciso de usar numa função de verificação de primalidade de um número).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não percebo muito bem como tenho de usar essa função porque também não percebi muito bem o que ela faz: "general coercion from integral types". O que tenho é isto:

primoOpt :: Int -> Bool
primoOpt n = null [x | x <- [2..sqrt(n)] , mod n x == 0]

Como é que agora uso essa função?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O teu problema está em que:

*Main> :t sqrt
sqrt :: (Floating a) => a -> a

*Main> :i Floating
class (Fractional a) => Floating a where
 pi :: a
 exp :: a -> a
 sqrt :: a -> a
 log :: a -> a
 (**) :: a -> a -> a
 logBase :: a -> a -> a
 sin :: a -> a
 tan :: a -> a
 cos :: a -> a
 asin :: a -> a
 atan :: a -> a
 acos :: a -> a
 sinh :: a -> a
 tanh :: a -> a
 cosh :: a -> a
 asinh :: a -> a
 atanh :: a -> a
 acosh :: a -> a
       -- Defined in GHC.Float
instance Floating Double -- Defined in GHC.Float
instance Floating Float -- Defined in GHC.Float

*Main> :t mod
mod :: (Integral a) => a -> a -> a

*Main> :i Integral
class (Real a, Enum a) => Integral a where
 quot :: a -> a -> a
 rem :: a -> a -> a
 div :: a -> a -> a
 mod :: a -> a -> a
 quotRem :: a -> a -> (a, a)
 divMod :: a -> a -> (a, a)
 toInteger :: a -> Integer
       -- Defined in GHC.Real
instance Integral Integer -- Defined in GHC.Real
instance Integral Int -- Defined in GHC.Real

Como podes ver, por defeito os únicos Floating são os floats e os doubles. E os únicos tipos que são Integral são o Int e o Integer.

Ou seja, para usares a função sqrt tens de transformar o teu int em float ou double. Consegues fazer isso com recurso à função fromIntegral com o Rui disse.

Depois ficas com 1 problema, ficas a dizer que queres uma lista de floats/doubles, poderás querer isso, mas não é boa ideia, já que poderás estar a criar uma lista maior que o ideal (depende do resultado da função sqrt), já que depois o último elemento na lista de compreensão irá depender se arredonda o valor para cima ou para baixo.

Neste caso aconselhava a usar a função truncate ignorando a parte decimal. Tinhas o acrescimo que já convertias o teu número para Int automaticamente para usar na função mod.

Ficavas então com o seguinte código.

primoOpt :: Int -> Bool
primoOpt n = null [x | x <- [2.. truncate (sqrt (fromIntegral n))] , mod n x == 0]

Mesmo se não quisesses arredondar o valor na definição da lista por compreensão, lembra-te que tinhas sempre que converter para int no momento em que aplicavas a função mode. Tanto num caso como no outro a lista de funções que podes ponderar em usar são sensivelmente as mesmas.

*Main> :i RealFrac
class (Real a, Fractional a) => RealFrac a where
 properFraction :: (Integral b) => a -> (b, a)
 truncate :: (Integral b) => a -> b
 round :: (Integral b) => a -> b
 ceiling :: (Integral b) => a -> b
 floor :: (Integral b) => a -> b
       -- Defined in GHC.Real
instance RealFrac Double -- Defined in GHC.Float
instance RealFrac Float -- Defined in GHC.Float

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora