printtype函数中的“ proxy a”是什么?

时间:2018-12-11 12:00:37

标签: haskell

当我尝试使用Type.Showtype中的printtype函数时。我发现printtype的类型签名是:

printtype :: Showtype a => proxy a -> IO ()

这里令人困惑的是proxy a的类型,它似乎来自Data.Proxy,但是我找不到proxy的任何定义,很明显,它与{ {1}},因为Proxy的首字母是小写。而且我知道在Haskell中数据类型的首字母不能小写,因此proxy不是类型,但是为什么它可以出现在类型签名中?

1 个答案:

答案 0 :(得分:6)

通常,类型a的代理是某种数据类型Proxy a,其值不包含任何信息。因此,该值将作为其类型的见证传递给(用于类型推断/类型检查)。在这种情况下,proxy不是特定的数据类型,而是类型为* -> *的类型变量。意思是您可以使用任何您想用作代理的东西,但是想法保持不变。

函数是

printtype :: Showtype a => proxy a -> IO ()

,它应该“打印类型”,但是函数适用于值而不是类型。因此,您无需传递实际类型为a的参数,而是传递某个类型为proxy a的参数,该参数的实际值无关紧要(通常是不包含任何信息的数据类型Proxy )。

查看实例的简单类型,例如对

instance (Showtype a, Showtype b) => Showtype '(a,b) where
  showtype _ = showtuple' [
    showtype (Proxy :: Proxy a),
    showtype (Proxy :: Proxy b)]

首先请注意showtype如何忽略其参数

showtype _ = ...

代理的值无关紧要,重要的是我们正在打印类型(a,b)。然后,我们调用showtuple',该调用用于打印给定列表的元组(任意长度),并打印每个组件的类型。对于每个组件,

showtype (Proxy :: Proxy a)
showtype (Proxy :: Proxy b)

这里选择的proxy是数据类型Proxy,不包含任何信息。在一种情况下,其类型为Proxy a,在另一种情况下,其类型为Proxy b。定义了函数showtype,以便您也可以使用例如

showtype ([] :: [a])
showtype ([] :: [b])

并不是说,如果您传递的是a而不是proxy a,那么对于通用a,唯一可以构造的值就是{{1} }。如果必须对其进行评估,则会破坏您的程序。