crypto.Random APIがcrypto-apiパッケージ内にあり、何かが "擬似乱数ジェネレータ"であることを指定します。元のクラス宣言を変更せずに、型クラスのインスタンスが別の型クラスにあることを宣言します。
私はつまり、StdGen、System.RandomのRandomGenクラスのインスタンスを使用して、このAPIを実装している:
instance CryptoRandomGen StdGen where
newGen bs = Right $ mkStdGen $ shift e1 24 + shift e2 16 + shift e3 8 + e4
where (e1 : e2 : e3 : e4 : _) = Prelude.map fromIntegral $ unpack bs
genSeedLength = Tagged 4
genBytes n g = Right $ genBytesHelper n empty g
where genBytesHelper 0 partial gen = (partial, gen)
genBytesHelper n partial gen = genBytesHelper (n-1) (partial `snoc` nextitem) newgen
where (nextitem, newgen) = randomR (0, 255) gen
reseed bs _ = newGen bs
しかし、この実装は唯一StdGenタイプのためですが、それは本当にシステムに何のために働くだろう.RandomのRandomGenのtypeclassです。
RandomGenのすべてが指定されたシム関数を使ってCryptoRandomGenのメンバーだと言う方法はありますか?これらの2つのライブラリのいずれかのソースを変更することなく、私自身のコードでこれを行うことができます。私の本能は、最初の行を次のように変更することです:
instance (RandomGen a) => CryptoRandomGen a where
しかし、それは構文的に正しいとは思われません。
ありがとうございます。 crypto-apiが必要とするセマンティクスをサポートしていないSystem.Randomについて、あなたが何を言っているかを完全に見ています。私は、おそらく楽しみのためのエクササイズとして、他の方法(RandomGenクラスのすべてのCryptoRandomGenインスタンスを作成する)を実装しようとします。しかし、私があなたのコードを読んでいるならば、呼び出し元は型チェックをするためにこの醜いACRG関数でRandomGenをラップアップしなければなりません。私はUndecidableInstancesを有効にするのが醜いことに対してそれを考慮する必要があるように見えます。 – Litherum
はい、あなたは正しいことを読んでいます。それは、クラスの特定のインスタンスを選択するために新しいタイプを作る、一般的なトリックです。 –