В настоящее время я изучаю 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, но у меня пока нет опыта работы с такими расширениями.
Заранее спасибо!
РЕДАКТИРОВАТЬ:
Для записи, теперь мое решение, основанное на полезном ответе, таково:
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
master
) упростит типы нетривиальными и существенными способами, например, не потребуетRankNTypes
(в некоторых сценариях?), Так что вы можете попробовать. - person Erik Kaplun   schedule 07.10.2015t
. Данный вопрос не имеет отношения к этому. - person Heinrich Apfelmus   schedule 08.10.2015