【发布时间】:2014-11-20 16:10:05
【问题描述】:
在 Haskell 中,Proxy 是一个类型见证值,它可以轻松传递某些类型
data Proxy a = Proxy
class JSONSchema a where
schema :: Proxy a -> Schema
所以您可以通过schema (Proxy :: Proxy (Int,Char)) 获取 Int-Char-Tuple 的 JSON 表示形式(可能是一个数组)。
人们为什么要使用代理?在我看来,同样可以通过
class JSONSchema a where
schema :: Schema a
类似于Bounded 类型类的工作方式。
我首先认为在使用代理时获取某些给定值的架构可能会更容易,但这似乎不是真的:
{-# LANGUAGE ScopedTypeVariables #-}
schemaOf :: JSONSchema a => a -> Schema a
schemaOf (v :: x) = schema (Proxy :: Proxy x) -- With proxy
schemaOf (v :: x) = schema :: Schema x -- With `:: a`
schemaOf _ = schema -- Even simpler with `:: a`
另外,人们可能会担心Proxy 值是否真的在运行时被根除,这是使用:: a 方法时不存在的优化问题。
如果Bounded 采用的:: a 方法能以更短的代码和更少的优化担忧达到相同的结果,那么人们为什么要使用代理? 代理有什么好处?
编辑: 一些答案和评论者正确地指出:: a 方法用“无用”类型参数污染了data Schema = ... 类型——至少从普通数据结构本身的角度来看是这样,它从不使用a (see here)。
建议改用幻象类型Tagged s b,这样可以将两个关注点分开(Tagged a Schema 将非参数模式类型与类型变量a 结合在一起),这比@ 987654342@方法。
所以我的问题最好是代理与标记方法有什么好处?
【问题讨论】:
-
在这种情况下有一个选择,但您想要代理的示例是
typeRep :: Proxy a -> TypeRep。另一种方法是使用旧的方法,typfeOf :: a -> Typeable。但后者令人不快,因为您经常必须将其与typeOf (undefined :: T)一起使用,恕我直言,最好使用typeRep (Proxy :: Proxy T)。 -
我看不到与
Bounded的类比。使用 hackage.haskell.org/package/tagged-0.7.3/docs/Data-Tagged.html 提供的类型标签是使用代理的有效替代方法。这在某种程度上取决于您是否想要结果类型的额外类型参数。 -
@kosmikus 你是对的,使用
Tagged将是不污染我的Schema和无用的a的更清洁方法(因为对于Schema,a实际上永远不会用于数据声明的左侧)。我将在问题的末尾添加一点,说一个更好的问题是关于Proxy和Tagged之间的区别。 -
@augustss 我还不明白为什么
typeRep你需要代理。你能详细说明一下吗? -
关于
typeRep:通过表示的类型参数化TypeRep会破坏它的有用性。如果没有代理,typeRep的类型将是Typeable a => TypeRep。
标签: haskell