编译错误 - 无法推断出Ord

Ped*_*des 3 haskell types

nRaizes :: Floating a => a -> a -> a -> a
  nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else if r == 0
                     then 1
                     else 2
Run Code Online (Sandbox Code Playgroud)

所以我得到了这个代码,我正在检查方程的根数.但是当我尝试编译它时,它给了我这个.

 Could not deduce (Ord a) arising from a use of ‘<’
    from the context (Floating a)
      bound by the type signature for
                 nRaizes :: Floating a => a -> a -> a -> a
      at Ficha1.hs:29:14-43
    Possible fix:
      add (Ord a) to the context of
        the type signature for nRaizes :: Floating a => a -> a -> a -> a
    In the expression: r < 0
    In the expression: if r < 0 then 0 else if r == 0 then 1 else 2
    In the expression:
      let r = b ^ 2 - 4 * a * c
      in if r < 0 then 0 else if r == 0 then 1 else 2

Ficha1.hs:33:32:
    Could not deduce (Eq a) arising from a use of ‘==’
    from the context (Floating a)
      bound by the type signature for
                 nRaizes :: Floating a => a -> a -> a -> a
      at Ficha1.hs:29:14-43
    Possible fix:
      add (Eq a) to the context of
        the type signature for nRaizes :: Floating a => a -> a -> a -> a
    In the expression: r == 0
    In the expression: if r == 0 then 1 else 2
    In the expression: if r < 0 then 0 else if r == 0 then 1 else 2
Run Code Online (Sandbox Code Playgroud)

是的,我是个傻瓜.我甚至不能理解什么是错的.这是一个浮动数字,为什么不能比较呢?我只知道它与签名有关,因为如果我删除它就可以了

Wil*_*sem 10

这是一个浮动数字,为什么不能比较呢?

不,它本身不是浮点数.Floating严格来说意味着你可以对它执行三角函数双曲函数.这是否意味着它是一个浮点数,是一个不同的方面(尽管它有点相关).

话虽这么说,但这样也不能意味着你可以比较两个元素.但这不是问题:我们可以Ord a为它添加类型类:

nRaizes :: (Floating a, Ord a) => a -> a -> a -> a
nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else
                         if r == 0
                         then 1
                         else 2
Run Code Online (Sandbox Code Playgroud)

但我们定义我们的功能太严格了.为什么我们需要三角函数和双曲函数?为什么不用*所有可能的数字表示定义函数Ord?因此我们可以将函数概括为:

nRaizes :: (Num a, Ord a) => a -> a -> a -> a
nRaizes a b c = let r = b^2 - 4 * a * c
                  in if r < 0
                     then 0
                     else
                         if r == 0
                         then 1
                         else 2
Run Code Online (Sandbox Code Playgroud)

此外,虽然大多数人喜欢圣诞节.大多数程序员不喜欢圣诞树作为函数定义.也许更优雅的方法是使用警卫而不是if- then- elses:

nRaizes :: (Num a, Ord a) => a -> a -> a -> a
nRaizes a b c | r < 0 = 0
              | r == 0 = 1
              | otherwise = 2
    where r = b*b - 4*a*c
Run Code Online (Sandbox Code Playgroud)

最后,我们产生三种可能的输出:0,1,和2.但没有什么说的输出类型应该是一样的类型a,bc.所以我们可以将输入和输出的类型分成:

nRaizes :: (Num a, Ord a, Num b) => a -> a -> a -> b
nRaizes a b c | r < 0 = 0
              | r == 0 = 1
              | otherwise = 2
    where r = b*b - 4*a*c
Run Code Online (Sandbox Code Playgroud)