Ericson Willians
Ericson Willians

Reputation: 7845

How to use sqrt with floor and ceiling?

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

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

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

Related Questions