module FRP.Helm.Random (
range,
float,
floatList
) where
import Control.Applicative (pure)
import Control.Monad (liftM, join, replicateM)
import FRP.Elerea.Param hiding (Signal)
import qualified FRP.Elerea.Param as Elerea (Signal)
import FRP.Helm.Signal
import FRP.Helm.Sample
import FRP.Helm.Engine
import System.Random (Random, randomRIO)
range :: Int -> Int -> Signal a -> Signal Int
range x y = rand (x,y)
float :: Signal a -> Signal Float
float = rand (0,1)
rand :: (Random a, Num a) =>
(a, a) -> Signal b -> Signal a
rand limits s = Signal $ do
s' <- signalGen s
rs :: Elerea.Signal (SignalGen Engine (Elerea.Signal a))
<- randomGens limits s'
r :: Elerea.Signal (Elerea.Signal a)
<- generator rs
transfer2 (pure 0) update_ s' (join r)
where
update_ :: (Random a, Num a) => p ->
Sample b -> a -> Sample a -> Sample a
update_ _ new random old = case new of
Changed _ -> Changed random
Unchanged _ -> Unchanged $ value old
randomGens :: (Random a, Num a) =>
(a,a) -> Elerea.Signal (Sample b)
-> SignalGen p (Elerea.Signal
(SignalGen p (Elerea.Signal a)))
randomGens l = transfer (return (return 0)) (makeGen l)
makeGen ::(Random a, Num a) => (a,a) -> p -> Sample b
-> SignalGen p (Elerea.Signal a)
-> SignalGen p (Elerea.Signal a)
makeGen l _ new _ = case new of
Changed _ -> effectful $ randomRIO l
Unchanged _ -> return $ return 0
floatList :: Signal Int -> Signal [Float]
floatList s = Signal $ do
s' <- signalGen s
fl :: Elerea.Signal (SignalGen Engine (Elerea.Signal [Float]))
<- floatListGens s'
ss :: Elerea.Signal (Elerea.Signal [Float])
<- generator fl
transfer2 (pure []) update_ s' (join ss)
where
floatListGens :: Elerea.Signal (Sample Int)
-> SignalGen p (Elerea.Signal
(SignalGen p (Elerea.Signal [Float])))
floatListGens = transfer (return (return [])) makeGen
makeGen _ new _ = case new of
Changed n -> liftM sequence $ replicateM n
$ effectful
$ randomRIO (0,1)
Unchanged _ -> return (return [])
update_ _ int new old = case int of
Changed _ -> Changed new
Unchanged _ -> Unchanged $ value old