Data.Proxy的目的是什么? [英] What is the purpose of `Data.Proxy`?

查看:118
本文介绍了Data.Proxy的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<$> 代理 c $ c> Data.Proxy 似乎只不过是一个单纯的

 数据代理s 

何时需要这样的无人居住的类型,它是什么让我无法做到,否则,与其他方法相比,它是什么时候简化了事情?它是如何用于实践的?

解决方案

我经常在 Data.Tagged 中使用代理,因为 documentation 指出,以避免不安全地传递虚拟参数。



例如,

  data Q 

类模数a其中
值: :标记一个Int

实例Modulus Q其中
value = Tagged 5

fxy =(x + y)`mod`(代理值(Proxy :: Proxy Q ))

如果没有 Tagged ,另一种编写方式是

  data Q 

class Modulus a where
value :: Proxy a - > Int

实例模数Q其中
值_ = 5

fxy =(x + y)`mod`(value(Proxy :: Proxy Q))

在这两个示例中,我们也可以删除 Proxy 类型,只需使用 undefined :: Q 即可传入幻像类型。但是,使用不确定的是一般在因为眉头一皱如果这个价值被评估过,那么问题可能会随之而来。考虑以下几点:

  data P =三
|默认

实例模数P其中
值三= 3
值_ = 5

fxy =(x + y)`mod`(value(undefined :: P))

如果我使用默认构造函数,程序会崩溃,因为我试图评估 undefined 。因此,代理类型为幽灵类型提供了类型安全性。

编辑



正如Carl指出的那样, Proxy 的另一个好处是可以使用<$ c $以外的幻像类型C> * 。例如,我瞎搞类型列表:

  { - #语言KindSignatures,DataKinds,TypeOperators,
MultiParamTypeClasses,PolyKinds,FlexibleContexts,
ScopedTypeVariables# - }

进口Data.Tagged
进口Data.Proxy

类Foo(A :: [* ])b其中
foo ::标记a [b]

实例Foo'[] Int其中
foo =标记[]

实例Foo xs Int)=> Foo(x':xs)Int其中
foo =标记$ 1:(proxy foo(Proxy :: Proxy xs)) - xs has kind [*]

toUnary :: [ Int]
toUnary = proxy foo(Proxy :: Proxy'[Int,Bool,String,Double,Float])

然而,由于未定义是一个,所以它的类型必须是 * 。如果我试图在我的例子中使用 undefined ,我需要类似于 undefined ::'[Int,Bool,String,Double,Float]
$ p















$ OpenKind',
但是'[Int,Bool,String,Double,Float]有'[*]'

欲了解更多信息,请查看出。鉴于错误消息,我希望能够写入 undefined :: Int#,但我仍然得到错误 Could not match kind#against * ,所以显然这是一个可怜的GHC错误信息,或者是我的一个简单的错误。


Proxy from Data.Proxy seems to be nothing more than a mere

data Proxy s

When do I need such an uninhabited type or rather, what does it enable I couldn't do otherwise, when does it simplify things compared to other approaches, and how is it used in practice?

解决方案

I frequently use Proxy with its partner in crime Data.Tagged, as the documentation indicates, to avoid unsafely passing dummy arguments.

For example,

data Q

class Modulus a where
  value :: Tagged a Int

instance Modulus Q where
  value = Tagged 5

f x y = (x+y) `mod` (proxy value (Proxy::Proxy Q))

An alternative way to write that without Tagged is

data Q

class Modulus a where
  value :: Proxy a -> Int

instance Modulus Q where
  value _ = 5

f x y = (x+y) `mod` (value (Proxy::Proxy Q))

In both examples, we could also remove the Proxy type and just use an undefined :: Q to pass in the phantom type. However, using undefined is generally frowned upon because of the problems that can ensue if that value is ever evaluated. Consider the following:

data P = Three
       | Default

instance Modulus P where
  value Three = 3
  value _ = 5

f x y = (x+y) `mod` (value (undefined :: P))

which is a valid way to write the instance if I use the Default constructor, the program would crash since I'm trying to evaluate undefined. Thus the Proxy type gives type safety for phantom types.

EDIT

As Carl pointed out, another benefit of Proxy is the ability to have a phantom type of kind other than *. For example, I'm messing around with type lists:

{-# 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])

However, since undefined is a value, its type must have kind * or #. If I tried to use undefined in my example, I'd need something like undefined :: '[Int, Bool, String, Double, Float], which results in the compile error:

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

For more on kinds, check this out. Given the error message, I expected to be able to write undefined :: Int#, but I still got the error Couldn't match kind # against *, so apparently this is a case of a poor GHC error message, or a simple mistake on my part.

这篇关于Data.Proxy的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆