packages feed

machinecell-4.0.0: test/Types/RuleSpec.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Arrows #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}

module
Types.RuleSpec
where

import qualified Control.Arrow.Machine as P

import Control.Arrow.Machine hiding (filter, source)
import Control.Applicative
import qualified Control.Category as Cat
import Control.Arrow
import Control.Monad.State
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Identity (Identity, runIdentity)
import Debug.Trace
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck (Arbitrary, arbitrary, oneof, frequency, sized)

import Common.RandomProc


spec =
  do
    describe "ProcessA as Category" $ catSpec
    describe "ProcessA as Arrow" $ arrSpec
    describe "Rules for ArrowLoop" $ arrowLoopSpec

catSpec =
  do
    prop "has asocciative composition" $ \fx gx hx cond ->
      let
          f = mkProc fx
          g = mkProc gx
          h = mkProc hx
          equiv = mkEquivTest cond
        in
          ((f >>> g) >>> h) `equiv` (f >>> (g >>> h))

    prop "has identity" $ \fx gx cond ->
      let
          f = mkProc fx
          g = mkProc gx
          equiv = mkEquivTest cond
        in
          (f >>> g) `equiv` (f >>> Cat.id >>> g)

arrSpec =
  do
    it "can be made from pure function(arr)" $
      do
        (run . arr . fmap $ (+ 2)) [1, 2, 3]
          `shouldBe` [3, 4, 5]

    prop "arr id is identity" $ \fx gx cond ->
      let
          f = mkProc fx
          g = mkProc gx
          equiv = mkEquivTest cond
        in
          (f >>> g) `equiv` (f >>> arr id >>> g)

    it "can be parallelized" $
      do
        pendingWith "to correct"
{-
        let
            myProc2 = repeatedlyT (Kleisli . const) $
              do
                x <- await
                lift $ modify (++ [x])
                yield `mapM` (take x $ repeat x)

            toN = evMaybe Nothing Just
            en (ex, ey) = Event (toN ex, toN ey)
            de evxy = (fst <$> evxy, snd <$> evxy)

            l = map (\x->(x,x)) [1,2,3]

            (result, state) =
                stateProc (arr de >>> first myProc2 >>> arr en) l

        (result >>= maybe mzero return . fst)
            `shouldBe` [1,2,2,3,3,3]
        (result >>= maybe mzero return . snd)
            `shouldBe` [1,2,3]
        state `shouldBe` [1,2,3]
-}

    prop "first and composition." $ \fx gx cond ->
      let
          f = mkProc fx
          g = mkProc gx
          equiv = mkEquivTest2 cond
        in
          (first (f >>> g)) `equiv` (first f >>> first g)

    prop "first-second commutes" $  \fx cond ->
      let
          f = first $ mkProc fx
          g = second (arr $ fmap (+2))

          equiv = mkEquivTest2 cond
        in
          (f >>> g) `equiv` (g >>> f)

    prop "first-fst commutes" $  \fx cond ->
      let
          f = mkProc fx
          equiv = mkEquivTest cond
                ::(MyTestT (Event Int, Event Int) (Event Int))
        in
          (first f >>> arr fst) `equiv` (arr fst >>> f)

    prop "assoc relation" $ \fx cond ->
      let
          f = mkProc fx
          assoc ((a,b),c) = (a,(b,c))

          equiv = mkEquivTest cond
                ::(MyTestT ((Event Int, Event Int), Event Int)
                           (Event Int, (Event Int, Event Int)))
        in
          (first (first f) >>> arr assoc) `equiv` (arr assoc >>> first f)

arrowLoopSpec =
  do
    let
        fixcore f y = if y `mod` 5 == 0 then y else y + f (y-1)
        pure (evx, f) = (f <$> evx, fixcore f)
        apure = arr pure

    prop "left tightening" $ \fx cond ->
      let
          f = mkProc fx

          equiv = mkEquivTest cond
        in
          (loop (first f >>> apure)) `equiv` (f >>> loop apure)

    prop "right tightening" $ \fx cond ->
      let
          f = mkProc fx

          equiv = mkEquivTest cond
        in
          (loop (apure >>> first f)) `equiv` (loop apure >>> f)