{----------------------------------------------------------------------------- Reactive Banana Test cases and examples ------------------------------------------------------------------------------} {-# LANGUAGE Rank2Types, NoMonomorphismRestriction #-} module Reactive.Banana.Tests where import Control.Monad (when) import Reactive.Banana.Model as Model import Reactive.Banana.Implementation as Impl import Test.QuickCheck {----------------------------------------------------------------------------- Testing ------------------------------------------------------------------------------} matchesModel :: (Typeable a, Show b, Eq b) => (forall f. FRP f => Event f a -> Event f b) -> [a] -> IO Bool matchesModel f = \xs -> do let bs1 = Model.interpret f xs bs2 <- Impl.interpret f xs when (bs1 /= bs2) $ print bs1 >> print bs2 return $ bs1 == bs2 testSuite = do -- trivial unit tests test add1 test filtering test counter test double test sharing test decrease test accumBvsE -- TODO: -- * algebraic laws -- * larger examples -- * quickcheck where test :: (Show b, Eq b) => (forall f. FRP f => Event f Int -> Event f b) -> IO () test f = print =<< matchesModel f [1..8::Int] {----------------------------------------------------------------------------- Examples ------------------------------------------------------------------------------} test f = Impl.interpret f [1..8::Int] add1 = fmap (+1) filtering = filterE (>= 3) . fmap (subtract 1) counter e = apply (pure const <*> bcounter) e where bcounter = accumB 0 $ fmap (\_ -> (+1)) e double e = union e e sharing e = union e1 e1 where e1 = filterE (< 3) e type Dummy = Int -- counter that can be decreased as long as it's >= 0 decrease :: FRP f => Event f Dummy -> Event f Int decrease edec = apply (const <$> bcounter) ecandecrease where bcounter = accumB 4 $ (subtract 1) <$ ecandecrease ecandecrease = whenE ((>0) <$> bcounter) edec -- test accumE vs accumE accumBvsE :: FRP f => Event f Dummy -> Event f Int accumBvsE input = e1 `union` e2 where e = input `union` input e1 = accumE 0 ((+1) <$ e) e2 = let b = accumB 0 ((+1) <$ e) in apply (const <$> b) e