无法真正遵循下面的类型推断,其中案例1有效但案例2失败,为什么?
ghci> :t sqrt . maximum . map (+1) -- case 1
(Floating c, Ord c) => [c] -> c
ghci> :t sqrt . maximum . map length -- case 2
Could not deduce (Floating Int) arising from a use of ‘sqrt’
from the context (Foldable t)
bound by the inferred type of it :: Foldable t => [t a] -> Int
@EDIT
在OOP上,Num
通常是subtypes
所有Int
的下限。 Float
和Int
。因此,如果Num
是限定类型,则Int
将被推断,但反之亦然。
此外,在类C语言中,内置数字转换可以自动满足从较低精度到较高精度的情况。从Float
到Num
。
相比之下,在HM type system的Haskell上,class
是其所有instances
的{{1}},例如Int
。 subclasses
和Floating
例如Num
。合格类型可以在祖先和后代之间进行双推理,例如从Int
到Floating
,Int
,反之亦然,但不在Floating
和Int
之间。
要解决案例2,Num
应首先适应fromIntegral
Data.List.genericLength
或使用Num
生成Floating
- 推理限定类型sqrt
要求的ghci> :t (+)
Num a => a -> a -> a
ghci> :t 1.1
Fractional a => a
ghci> :i Fractional
class Num a => Fractional a
instance Fractional Float
instance Fractional Double
ghci> :t 1
Num a => a
ghci> :t length [1]
Int
ghci> :i Int
instance Num Int
instance Real Int
instance Integral Int
ghci> :t 1.1 + 1 -- case 1
Fractional a => a
ghci> :t 1.1 + length [1] -- case 2
No instance for (Fractional Int) arising from the literal ‘1.1’
。
让我们应用上述要点来遵循下面的类型推断,
class A
{
public:
virtual void func();
virtual void func2();
}
class B : public A
{
public:
void func();
}
class C : public A
{
public:
void func2()
}
答案 0 :(得分:4)
1
可以是任何类型的数字,+
可以使用任何类型的数字。 maximum
也是如此。因此maximum . map (+1)
是一个函数,可以获取任何类型的数字列表,并生成与其结果相同类型的数字。这包括整数和浮点数。
但是length
会专门生成Int
。它不能产生任何其他类型的数字。因此maximum . map length
可以获取任何列表并生成Int
类型的结果,而不是任何其他数字类型。
现在sqrt
需要将其参数作为浮点数。因此,在第一种情况下,类型推断表明您必须提供浮点数列表,因此maximum . map (+1)
的结果将是可以传递给sqrt
的浮点数。
然而,第二种情况根本无法奏效,因为Int
不是浮点类型而maximum . map length
不能生成除Int
以外的任何内容。所以这会导致错误。
您可以使用fromIntegral
函数将length
的结果转换为任何数字类型,以使第二个代码有效。