如何将 sqrt 与地板和天花板一起使用?

How to use sqrt with floor and ceiling?

当我尝试 运行 这段代码时,它的类型很混乱:

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)

所以sqrtFloating a => a -> a类型,floor(RealFrac a, Integral b) => a -> b类型。显然,我不能把它们混在一起。我已经使用 fromRational 和 fromIntegral 以及 toRational 进行了转换,但我无法阻止编译器抱怨:

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

如何将 sqrt 与 floor 一起使用?

sqrt n 要求 n 属于 Floating 类型类的成员类型,因为 sqrt 具有类型 sqrt :: Floating a => a -> a。没有同时属于 IntegralFloating 类型类的内置数值类型:这没有多大意义,因为两者处理不同种类的数字。

您可以使用 fromIntegral :: (Integral a, Num b) => a -> b 将任何 Integral 类型的数字转换为任何 Num 类型。因此,我们可以将其用于:

isSquare :: Integral n => n -> Bool
isSquare n = floor root == ceiling root
  where root = sqrt (<strong>fromIntegral</strong> n)