私は現在、反応性バナナを使用してFRPを学習しており、ランダム関数のストリームを作成したいと考えていました。私はこれを作ってみた:多相関数のイベントストリームを作成できますか?はいの場合、どうですか?
-- | take number generator, and some pulse event stream, generate random function stream
mkRandom :: (Random a,RandomGen g) => g -> Event t b -> Event t ((a,a) -> a)
mkRandom rng es = (\f -> \r -> fst $ f r) <$> (accumE first $ next <$> es)
where first = flip randomR rng
next _ prev range = randomR range g
where (a,g) = prev range
動作しているようですが、私はこのようにそれを使用することができます:私はの番号を生成し、そのストリームを共有しようとすると、
randFuncs = mkRandom rnd (pulse 1000 time)
some = ($ (0,10::Int)) <$> randFuncs
しかし、当然のことながら別のタイプ:
some2 = ($ (0,10::Double)) <$> randFuncs
タイプチェッカーは私が理解しています。その後、私は次のように関数を一般化しようとした:
mkRandom :: (RandomGen g) => g -> Event t b -> Event t (forall a. Random a => (a,a) -> a)
その後、GHCは違法多型署名について、私はImpredicativeTypesを有効にしたいかどうかを訴えました。私はそれを行い、それを動作させるためにすべての注釈をつけようとしばらくしていましたが、GHCは常に型にマッチできないと訴えました。
私の質問は - 私がしたいことは可能ですか?そのためにImpredicativeTypesが本当に必要なのですか、それとも間違っていますか?
私はRankNTypesで十分だと思っていましたが、まだそのような拡張機能の経験はありません。
ありがとうございます!
EDIT:レコードの
、今役に立つ応答に基づいて、私の解決策は次のとおりです。
newtype RandomSource = Rand { getRand :: forall a. (Random a) => (a,a) -> [a] }
-- | take number generator and some pulse event stream, generate randomness stream
mkRandom :: RandomGen g => g -> Event t a -> Behavior t RandomSource
mkRandom rng es = fst <$> (accumB (next id (id,rng)) $ next <$> es)
where next _ (_,rng) = (Rand $ flip randomRs g1, g2)
where (g1,g2) = split rng
-- | take a rand. source, a range and a pulse, return stream of infinite lists of random numbers
randStream :: Random a => Behavior t RandomSource -> (a,a) -> Event t b -> Event t [a]
randStream funcs range pulse = ($ range) . getRand <$> funcs <@ pulse
「RankNTypes」(いくつかのシナリオでは?)を必要としないなど、簡単で実質的な方法で型を単純化するために、banana 1.0(現在の 'master')が反応すると言われています。試してみる。 –
@ErikAllik反応バナナ1のAPIが変更されました。0は主に型パラメータ 't'に関係します。手元の問題はこれとは無関係です。 –