我的 sqrt 函数不会在 GHCi 中编译

my sqrt function will not compile in GHCi

我想计算 Int 的平方根,Prelude sqrt 函数用于 Float ⟶ Float,我需要 Int ⟶ Float.

尝试推出我自己的简单 sqrt 我定义了两种类型并从 Hackage 上的 Prelude 源代码复制了函数: sqrt x = x ** 0.5

所以:

sqrt' :: Int -> Float
sqrt' x = x ** 0.5

给出错误:

    • Couldn't match expected type ‘Float’ with actual type ‘Int’
    • In the expression: x ** 0.5
      In an equation for ‘sqrt'’: sqrt' x = x ** 0.5
   |
19 | sqrt' x = x ** 0.5 
   |           ^^^^^^^^

我尝试了不同类型的 class 定义,使用中间变量和 where 子句等等,但没有成功。

编辑 ⟶

p 285 摘自 The Haskell Book which is a prettier version of the Haskell documentation illustration here.

(**) :: Floating a => a -> a -> a can only be applied to Floating 类型,并且要求操作数和结果都具有相同的类型。

另一方面,您的类型签名表示 xIntInt 而不是 的成员Floating typeclass),而且 x ** 0.5 应该 return a Float,所以这违反了 (**).

的类型签名

我们可以转换属于 Integral typeclass to any type that is a member of the Num typeclass with fromIntegral :: (Integral a, Num b) => a -> b 的任何类型。在这种情况下,fromIntegral 会将 Int 转换为 Float:

sqrt' :: Int -> Float
sqrt' x = <b>fromIntegral</b> x ** 0.5
isqrt :: Int -> Float   -- but realy, 
-- (Integral a, Floating b) =>         a    ->    b
isqrt n = sqrt $ fromIntegral n

首先会起作用。

它的工作原理是sqrt :: Float -> Float(或Double -> Double,但实际上

sqrt         :: Floating         b =>       b ->  b

) 需要它的参数是正确的类型,并且

fromIntegral :: (Integral a, Num b) => a -> b

完成任务。

任何 Integral 类型已经是 Num 任何 Floating 类型也是如此:

> :i Integral
class (Real a, Enum a) => Integral a where    -- subclass of Real
  ......
  toInteger :: a -> Integer

> :i Real
class (Num a, Ord a) => Real a where      -- subclass of Num
  ......

> :i Num
class Num a where
  ......
  fromInteger :: Integer -> a

> :i Floating
class Fractional a => Floating a where    -- subclass of Fractional
  ......

> :i Fractional
class Num a => Fractional a where         -- subclass of Num
  ......