Reputation: 7845
It's type mayhem when I try to run this code:
isSquare :: Integral n => n -> Bool
isSquare n = result
where
root = sqrt n
f = floor root
c = ceiling root
result = f == c
main = do
print (isSquare 25)
So sqrt
is of type Floating a => a -> a
and floor
is of type (RealFrac a, Integral b) => a -> b
. Apparently, I can't mix them. I've converted using fromRational and fromIntegral and toRational and I just can't stop the compiler from complaining:
Main.hs:4:12: error:
* Could not deduce (Floating n) arising from a use of `sqrt'
from the context: Integral n
bound by the type signature for:
isSquare :: forall n. Integral n => n -> Bool
at Main.hs:1:1-35
Possible fix:
add (Floating n) to the context of
the type signature for:
isSquare :: forall n. Integral n => n -> Bool
* In the expression: sqrt n
In an equation for `root': root = sqrt n
In an equation for `isSquare':
isSquare n
= result
where
root = sqrt n
f = floor root
c = ceiling root
result = f == c
|
4 | root = sqrt n
| ^^^^^^
Main.hs:5:9: error:
* Could not deduce (RealFrac n) arising from a use of `floor'
from the context: Integral n
bound by the type signature for:
isSquare :: forall n. Integral n => n -> Bool
at Main.hs:1:1-35
Possible fix:
add (RealFrac n) to the context of
the type signature for:
isSquare :: forall n. Integral n => n -> Bool
* In the expression: floor root
In an equation for `f': f = floor root
In an equation for `isSquare':
isSquare n
= result
where
root = sqrt n
f = floor root
c = ceiling root
result = f == c
|
5 | f = floor root
| ^^^^^^^^^^
Main.hs:6:9: error:
* Could not deduce (RealFrac n) arising from a use of `ceiling'
from the context: Integral n
bound by the type signature for:
isSquare :: forall n. Integral n => n -> Bool
at Main.hs:1:1-35
Possible fix:
add (RealFrac n) to the context of
the type signature for:
isSquare :: forall n. Integral n => n -> Bool
* In the expression: ceiling root
In an equation for `c': c = ceiling root
In an equation for `isSquare':
isSquare n
= result
where
root = sqrt n
f = floor root
c = ceiling root
result = f == c
|
6 | c = ceiling root
| ^^^^^^^^^^^^
exit status 1
How can I use sqrt with floor?
Upvotes: 1
Views: 150
Reputation: 476659
sqrt n
requires n
to be of a type that is a member of the Floating
typeclass, since sqrt
has type sqrt :: Floating a => a -> a
. There are no builtin numerical types that are both a member of the Integral
and Floating
typeclass: that would not make much sense since the two deal with different sorts of numbers.
You can use fromIntegral :: (Integral a, Num b) => a -> b
to convert a number of any Integral
type to any Num
type. We thus can use this with:
isSquare :: Integral n => n -> Bool
isSquare n = floor root == ceiling root
where root = sqrt (fromIntegral n)
Upvotes: 4