2017-04-04 24 views
1

私のアプリケーションでは、型が(パラメータ)dの(注入)関数である式を構築しています。たとえば:注入型関数に入力を与える方法

op :: Proxy d -> Proxy ('S d) 
op _ = Proxy 

foo :: forall d . Proxy ('S ('S d)) 
foo = op $ op Proxy 

私はfooのような式を構築した後、私はそれを解釈したいと思います:

getValue :: Proxy (d :: Nat) -> Int 
getValue _ = ... 

fooを解釈するために、私はタイプのアプリケーションの構文を使用して、getValue $ foo @'Zを呼び出すことができます。私の意図が常にこのパターンでgetValueと呼ぶことを除いて、それはまあまあです。したがって、ユーザーにの式を'Zに相対的に指定する必要はなく、getValueに固有のプロパティである場合は、getValue fooと書くことができ、おそらくは2になると思います。

NB:foo :: Proxy d -> Proxy ('S ('S d))getValue :: (Proxy d1 -> Proxy d2) -> Int、その後、getValue'Zに関数を適用している:一つの解決策はProxyと明示的な機能入力への入力を行うことです。これは私が望むものを実現しますが、余分なものはProxyです。この余分なものを必要としない方法はありますかProxy

+0

単なる好奇心:なぜシングルトンを使用しないのですか? – Alec

+0

私はすでにNatの値の周りにラッパーでシングルトンを使用していますので、アプローチを提案したい場合は全く問題ありません。 – crockeea

+0

問題は 'Proxy :: Proxy t'ですが、あなたは' _Z :: Proxy 'Z'を望んでいます - それであなた自身でそのような定数を定義するだけです。この作業を 'getValue'に移さなければならない場合は、インスタンスオーバーラップを使って"自由 "型変数を' 'Z''にインスタンス化することができますが、本当に価値がありません。 – user2407038

答えて

-2

getValuegetValue'に変更し、getValue foo = getValue' $ foo @'Zと書きます。

class ReifyNat (n :: Nat) where 
    reifyNat :: Integer 

instance ReifyNat 'Z where 
    reifyNat = 0 

instance ReifyNat n => ReifyNat ('S n) where 
    reifyNat = succ (reifyNat @n) 

getValue :: forall n. ReifyNat n => Proxy n -> Integer 
getValue _ = reifyNat @n 

それとも使用します:

getValue :: (forall (d :: Nat). Proxy d) -> Int 
getValue foo = getValue' $ foo @'Z 

getValue' :: Proxy (d :: Nat) -> Int 
getValue' Proxy = ... 

はここにそれがあなたの最終目標であるならば自然数を具体化するためのより良い方法だ

getValue :: forall n. ReifyNat n => Integer 
getValue = reifyNat 

あなたはおそらく、すべてのを取り除くことができますあなたが望むなら、この方法でProxyの使用。

+0

私はあなたの最初の行が可能ではないと考えましたか? 'getValue'引数が型アプリケーションをとることができることをコンパイラに伝えなければなりません。あなたの 'getValue'の型は何ですか? – crockeea

+2

ここでのポイントは 'Nat'の値を反映するものではありません(これは単なる例です)。ポイントは、 'getValue'を呼び出すときに型関数への入力を自動的に提供することです。実際にコンパイルされた場合、最初のアプローチはそのトリックを行います。 – crockeea

+0

@crockeeaあなたの問題は、より一般的な「特定の 'y'を引数として取るのではなく、常に' 'fx y''を使う方法の特定の場合です。答えは関数 'f 'x = f x someFixedY'を作ることです。明示的な 'forall':' getValue ':: forall(n :: Nat)を追加しなければならないかもしれません。 Int。型引数を値レベルのプロキシラムダから型レベルの大文字のラムダに移動するだけです。 – Lazersmoke

関連する問題