Data.Proxy的目的是什么?

Data.Proxy Proxy似乎只不过是一个单纯的

 data Proxy s 

我什么时候需要这样一种无人居住的types,或者说是什么使我无法做到的,什么时候与其他方法相比简化了事情,它是如何在实践中使用的?

我经常使用Proxy与犯罪Data.Tagged伙伴,如文档指出,以避免不安全地传递虚拟参数。

例如,

 data Q class Modulus a where value :: Tagged a Int instance Modulus Q where value = Tagged 5 fxy = (x+y) `mod` (proxy value (Proxy::Proxy Q)) 

另一种方式来写没有Tagged

 data Q class Modulus a where value :: Proxy a -> Int instance Modulus Q where value _ = 5 fxy = (x+y) `mod` (value (Proxy::Proxy Q)) 

在这两个例子中,我们也可以删除Proxytypes,只需使用undefined :: Q来传入幻像types。 然而,使用未定义通常是不被接受的,因为如果这个价值被评估过,那么可能会出现问题。 考虑以下:

 data P = Three | Default instance Modulus P where value Three = 3 value _ = 5 fxy = (x+y) `mod` (value (undefined :: P)) 

这是一个有效的方法来编写实例, 如果我使用Default构造函数 ,程序会崩溃,因为我试图评估undefined 。 因此, Proxytypes为幻像types提供types安全性。

编辑

正如Carl指出的那样, Proxy另一个好处是能够拥有除*以外的幽灵types。 例如,我正在搞types列表:

 {-# LANGUAGE KindSignatures, DataKinds, TypeOperators, MultiParamTypeClasses, PolyKinds, FlexibleContexts, ScopedTypeVariables #-} import Data.Tagged import Data.Proxy class Foo (a::[*]) b where foo:: Tagged a [b] instance Foo '[] Int where foo = Tagged [] instance (Foo xs Int) => Foo (x ': xs) Int where foo = Tagged $ 1 : (proxy foo (Proxy :: Proxy xs)) -- xs has kind [*] toUnary :: [Int] toUnary = proxy foo (Proxy :: Proxy '[Int, Bool, String, Double, Float]) 

但是,因为undefined是一个 ,所以它的types必须有*# 。 如果我试图在我的例子中使用undefined ,我需要像undefined :: '[Int, Bool, String, Double, Float] ,这会导致编译错误:

 Kind mis-match Expected kind `OpenKind', but '[Int, Bool, String, Double, Float] has kind `[*]' 

有关更多种类,请检查此 。 鉴于错误消息,我希望能够写入undefined :: Int# ,但我仍然得到错误Couldn't match kind # against * ,显然这是一个糟糕的GHC错误信息,或一个简单的错误对我而言。