packages feed

machinecell-4.0.0: test/Types/LoopSpec.hs

{-# LANGUAGE Arrows #-}

module
    Types.LoopSpec
where

import Data.Functor
import Control.Arrow
import Test.Hspec

import Control.Arrow.Machine as P
import Control.Monad.Trans (liftIO)

import Data.IORef

import Common.RandomProc

doubler = arr (fmap $ \x -> [x, x]) >>> P.fork

spec =
  do
    it "is possible that value by `dHold` or `dAccum` can refer at upstream." $
      do
        ref <- newIORef ([] :: [Int])
        let
            pa :: ProcessT IO (Event Int) (Event ())
            pa = proc evx ->
              do
                rec
                    P.fire print -< y <$ evx
                    P.fire putStr -< "" <$ evx -- side effect
                    evx2 <- doubler -< evx
                    y <- P.dAccum 0 -< (+) <$> evx2
                fire (\x -> modifyIORef ref (x:)) -<  y <$ evx

        liftIO $ P.runT_ pa [1, 2, 3]
        ret <- readIORef ref
        reverse ret `shouldBe` [0, 1+1, 1+1+2+2]

    it "can be used with rec statement(pure)" $
      let
          a = proc ev ->
            do
              x <- hold 0 -< ev
              rec l <- returnA -< x:l
              returnA -< l <$ ev
          result = fst $ stateProc a [2, 5]
        in
          take 3 (result!!1) `shouldBe` [5, 5, 5]

    it "the last value is valid." $
      do
        let
            mc = repeatedly $
              do
                x <- await
                yield x
                yield (x*2)
            pa = proc x ->
              do
                rec y <- mc -< (+z) <$> x
                    z <- dHold 0 -< y
                returnA -< y
        run pa [1, 10] `shouldBe` [1, 2, 12, 24]

    it "carries no events to upstream." $
      do
        let
            pa = proc ev ->
              do
                rec r <- dHold True -< False <$ ev2
                    ev2 <- fork -< [(), ()] <$ ev
                returnA -< r <$ ev
        run pa [1, 2, 3] `shouldBe` [True, True, True]