は、私が使用して、この形状のデータ・タイプで働いているV
linear
から:KnownNat nにKnownNat(n * 3)などを含めることができますか?
type Foo n = V (n * 3) Double -> Double
私は右に渡していることを保証することができるようにしたいので、それは、かなり重要ですn
に固定持ちますコンパイル時の要素数。これは私がここでやっていることとは関係なく、すでにうまくいく私のプログラムの一部です。
KnownNat n
については、私のプログラムに必要な動作を満たすFoo n
を生成することができます。この質問の目的のために、
mkFoo :: KnownNat (n * 3) => Foo n
mkFoo = sum
以上有意義例えば、それは同じ長さのランダムV
を生成することができますし、2にdot
を使用するような愚かなものにすることができます。ここではKnownNat
の制約は冗長ですが、実際にはFoo
を作成する必要があります。私はFoo
を1つ作成し、それを私のプログラム全体(または複数の入力)に使用するので、私はいつでも同じ長さのものとFoo
の構造が指示するものを使用しています。
そして最後に、私はFoo
のための入力を作る機能があります。
bar :: KnownNat (n * 3) => Proxy n -> [V (n * 3) Double]
バーは、実際に私はタイプの関数としてn * 3
を使用して、代わりにだけ手動でそれを拡張していた理由であります。その理由は、bar
は、長さがn
の3つのベクトルを使用し、それらをすべて長さがn * 3
のベクトルとして追加することによってその仕事を行う可能性があるためです。また、n
は、意味的には、n * 3
よりもはるかに意味のあるパラメータです。また、これは私が今など、
を3の倍数ではありませんn
年代のような不適切な値を禁止することができます、前に、すべてがいる限り、私は最初に型シノニムを定義したとして罰金働いた:
type N = 5
そして、私はちょうどProxy :: Proxy N
をbar
に渡し、mkFoo :: Foo N
を使うことができます。そしてすべてがうまくいった。
-- works fine
doStuff :: [Double]
doStuff = let inps = bar (Proxy :: Proxy N)
in map (mkFoo :: Foo N) inps
しかし、今、私は、ファイルから、またはコマンドライン引数から情報をロードすることにより、実行時にN
を調整できるようにしたいです。
私はreflectNat
を呼び出すことによって、それをやってみました:
doStuff :: Integer -> Double
doStuff n = reflectNat 5 $ \[email protected](Proxy :: Proxy n) ->
let inps = bar (Proxy :: Proxy n)
in map (mkFoo :: Foo n) inps
しかし... bar
とmkFoo
はKnownNat (n * 3)
が必要ですが、reflectNat
はちょうど私KnownNat n
を与えます。
私はreflectNat
が私にfoo
を満足させるという証拠を一般化する方法はありますか?
いいえ、できません。あなたが達成しようとしていることについてもう少し文脈を伝えることができれば、誰かが助けてくれるかもしれません。 – dfeuer
短く、自己完結型、正しい(コンパイル可能)、例(sscce.org)を書いてみてください。 – Hjulle
@dfeuerは、意思決定の動機を十分に説明した具体的な例を追加しました。ありがとう! –