我在.hs文件中有以下代码
module TypeInference1 where
f :: Num a => a -> a -> a
f x y = x + y + 3
然后,如果我检查和的类型,则会得到以下结果,这是可以的:
*TypeInference1> :t f
f :: Num a => a -> a -> a
如果我将分数类型的一个参数传递给 f 并检查其类型,我将获得:
*TypeInference1> :t f 1.0
f 1.0 :: Fractional a => a -> a
但是另一方面,如果我通过对其中一个参数设置除法运算来更改和,则如下所示:
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
为什么会发生这种情况,为什么在按上述方式更改函数和时无法推断类型?
最佳答案
简短答案:通过指定Num a => a -> a -> a
,您声称f
可以处理属于a
类型类的所有Num
,但是(/)
仅可用于属于Fractional
类型类的类型。
Fractional
是Num
的“子”类型类。这意味着所有属于Fractional
的类型都是Num
的成员,但是反之亦然。
通过指定f的类型:
f :: Num a => a -> a -> a
您说
f
可以处理作为a
类型类成员的所有类型Num
。但这如果将f
定义为f x y = x/2 + y + 3
是不正确的,因为x/2
意味着x
应该是Fractional
的成员。实际上(/)
的类型为 (/) :: Fractional a => a -> a -> a
。因此,您应该使f
更具限制性,以便您只能传递a
类型的值,而a
是Fractional
类型类的成员:f :: Fractional a => a -> a -> a
f x y = x/2 + y + 3