避免类型注释

我们使用类型注释来避免歧义。类型应用程序可用于相同目的。例如

x::Num a => a
x = 5

main::IO ()
main = print x

此代码存在歧义错误。我们知道 a 有一个 Num 实例,为了打印它,我们知道它需要一个 Show 实例。如果 a 例如是 Int,这可能有效,所以要修复错误我们可以添加类型注释

main = print (x::Int)

使用类型应用程序的另一种解决方案如下所示

main = print @Int x

要理解这意味着我们需要查看 print 的类型签名。

print::Show a => a -> IO ()

该函数采用 a 类型的一个参数,但另一种查看它的方法是它实际上需要两个参数。第一个是类型参数,第二个是类型是第一个参数的值。

值参数和类型参数之间的主要区别在于,当我们调用它们时,后者会隐式地提供给函数。谁提供给他们?类型推理算法! TypeApplications 让我们做的是明确地给出那些类型参数。当类型推断无法确定正确的类型时,这尤其有用。

所以要打破上面的例子

print::Show a => a -> IO ()
print @Int::Int -> IO ()
print @Int x::IO ()