2014-03-01 63 views
35

ProxyData.Proxy似乎沒有什麼比一個單純的`Data.Proxy`的目的是什麼?

data Proxy s 

什麼時候需要這樣一個無人居住的類型或者更確切地說,是什麼使我不能做,否則,當它簡化事情比較到其他方法,以及它在實踐中如何使用?

+10

'代理s'不是一個無人居住的類型,它有一個單一的構造函數'代理'。 – Cactus

+4

特別是,'Proxy'似乎實際上被定義爲'數據代理s =代理'而不是數據代理s'寫在問題中。 –

回答

20

我經常使用Proxy與其合作伙伴Data.Tagged作爲documentation表示,以避免不安全地傳遞虛擬參數。

例如,

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)) 

的另一種方式來寫,沒有Tagged

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)) 

在兩個例子中,我們還可以刪除Proxy類型和只是使用一個undefined :: Q在傳遞幻影類型。但是,使用未定義的是generally frowned upon,因爲如果曾經評估過該值,則可能會出現問題。考慮以下幾點:

data P = Three 
     | Default 

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

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

這是寫的實例有效的方式,如果我用Default構造,程序會崩潰,因爲我想評價undefined。因此,Proxy類型爲幻像類型提供了類型安全性。

編輯

卡爾指出的,Proxy另一個好處是比*其他類型的假體類型的能力。例如,我瞎搞類型列表:

{-# 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,它的類型必須有一種*#。如果我想在我的例子使用undefined,我需要像undefined :: '[Int, Bool, String, Double, Float],這會導致編譯錯誤:

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

更多關於種,檢查this出來。鑑於錯誤信息,我希望能夠編寫undefined :: Int#,但我仍然得到了錯誤Couldn't match kind # against *,所以顯然這是一個糟糕的GHC錯誤信息或我的一個簡單的錯誤的情況。

+17

從最近版本的GHC開始,'Proxy'也是多色化的。你可以說'Proxy :: Proxy Maybe'。祝你好運,說'undefined ::也許'。 – Carl

+1

我不認爲我會考慮在Robert Harper的博客上發佈一篇文章,作爲Haskell社區對任何事物的立場的證據。特別是,我懷疑他會考慮在'undefined'上使用'Proxy'會對Haskell的安全性產生重大影響。當然,這並不意味着它會從這個答案中得到任何東西。 –

+0

爲什麼使用'proxy'而不是'unTagged'? – coppro