为什么我得到:无法推断出使用'/'引起的(分数a)?

Flo*_*ryn 3 haskell

我在.hs文件中有以下代码

module TypeInference1 where
f :: Num a => a -> a -> a
f x y = x + y + 3
Run Code Online (Sandbox Code Playgroud)

然后,如果我检查f的类型,则会得到以下结果,这是可以的:

*TypeInference1> :t f
f :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

如果我将一个分数类型的参数传递给f并检查其类型,则获得:

*TypeInference1> :t f 1.0
f 1.0 :: Fractional a => a -> a
Run Code Online (Sandbox Code Playgroud)

但是另一方面,如果我通过对其中一个参数设置除法运算来更改f,则如下: f x y = x/2 + y + 3

我收到以下错误:

5-typeInference1.hs:4:9: error:
    • Could not deduce (Fractional a) arising from a use of ‘/’
      from the context: Num a
        bound by the type signature for:
                   f :: forall a. Num a => a -> a -> a
        at 5-typeInference1.hs:3:1-25
      Possible fix:
        add (Fractional a) to the context of
          the type signature for:
            f :: forall a. Num a => a -> a -> a
    • In the first argument of ‘(+)’, namely ‘x / 2’
      In the first argument of ‘(+)’, namely ‘x / 2 + y’
      In the expression: x / 2 + y + 3
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,为什么在按上述方法更改函数f时无法推导类型?

Wil*_*sem 8

简短的答案:通过指定Num a => a -> a -> a您声明f可以处理属于typeclass 成员的所有 ,但只能使用属于typeclass 成员的类型。aNum(/)Fractional

Fractional是的“子”类型类Num。这意味着,作为其成员的所有类型Fractional的成员Num,但这并不会反之亦然任副。

通过指定f的类型:

f :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

你说f可以处理所有类型a属于的成员Num类型类。但是,如果将其定义ff x y = x/2 + y + 3,那是不正确的,因为这x/2意味着该x类型应该是的成员Fractional。确实(/)有类型(/) :: Fractional a => a -> a -> a。因此f,您应该进行更严格的限制,以便您只能传递a带有typeclass a成员Fractional类型的值:

f :: Fractional a => a -> a -> a
f x y = x/2 + y + 3
Run Code Online (Sandbox Code Playgroud)

  • 多态类型的基本原理是,函数的调用者可以在函数类型给定的约束内选择要提供的类型。原始的`f`可以在任何数值类型上使用,并且其所有参数都必须为同一类型。当它提供`1.0`时,可以是任何小数类型,这很好,并且会导致`Fractional`约束,因为`f`定义中的所有`a`都是相同的。但是,使用`/`运算符的第二个`f`突然不再适用于所有数值类型。您的类型签名说可以,这就是GHC拒绝它的原因。 (3认同)
  • 因为`Fractional`是`Num`的子类型,所以可以使用。因此,得出您的参数`1.0 ::分数b => b`与`Num a => a-> a-> a`中的`a`相同,因此结果的类型为`(Fractional a,Num a)=> a-> a`或更简单的`Fractional a => a-> a`。因此,“ f 1.0”仅适用于所有“分数”类型。 (2认同)