packages feed

express-1.0.14: test/map.hs

-- Copyright (c) 2019-2024 Rudy Matela.
-- Distributed under the 3-Clause BSD licence (see the file LICENSE).
import Test
import Test.LeanCheck.Function

import Data.Express.Utils.List (isNub)

main :: IO ()
main  =  mainTest tests 5040

tests :: Int -> [Bool]
tests n  =
  [ True

  -- the order should not matter for //
  , holds n $ \e ee1 ee2 -> fst ee1 /= fst ee2 ==> e // [ee1, ee2] == e // [ee2, ee1]
  , holds n $ \e ees -> isNub (map fst ees) ==> e // ees == e // reverse ees

  -- the order should not matter for //-
  , holds n $ \e ee1 ee2 -> fst ee1 /= fst ee2 ==> e //- [ee1, ee2] == e //- [ee2, ee1]
  , holds n $ \e ees -> isNub (map fst ees) ==> e //- ees == e //- reverse ees
  , holds n $ \e ees' -> let ees = map (mapFst unEV) ees' in
                         isNub (map fst ees) ==> e //- ees == e //- reverse ees

  -- //- and // are essentially different
  , exists n $ \e es ->  e // es  /=  e //- es

  -- equivalences between // and //-
  , holds n $ \e ees -> all (isValue . fst) ees ==> e // ees == e //- ees
  , holds n $ \e ees -> e // filter (isValue . fst) ees == e //- ees

  -- //- ignores replacements of non-variable values
  , holds n $ \e ees -> e //- filter (not . isValue . fst) ees == e

  -- (in)equivalences between maps
  , exists n $ \f e -> mapValues f e /= (mapVars f . mapConsts f) e
  , exists n $ \f e -> mapValues f e /= (mapConsts f . mapVars f) e
  , exists n $ \f e -> (mapVars f . mapConsts f) e /= (mapConsts f . mapVars f) e
  , exists n $ \f e -> (mapConsts f . mapVars f) e /= (mapVars f . mapConsts f) e
  -- the above should fail because of the following
  , let f _ = id' i_ in mapValues f zero == id' i_
                     && mapVars   f zero == zero
                     && mapConsts f zero == id' i_
                     && mapVars f (mapConsts f zero) == id' (id' i_)
                     && mapConsts f (mapVars f zero) == id' i_

  -- the following do not hold in general:
  , exists n $ \f e -> (mapValues f . mapValues f) e /= mapValues f e
  , exists n $ \f e -> (mapVars   f . mapVars   f) e /= mapVars   f e
  , exists n $ \f e -> (mapConsts f . mapConsts f) e /= mapConsts f e

  -- what actually holds is this:
  , holds n $ \f e -> (mapValues f . mapValues f) e == mapValues (mapValues f . f) e
  , holds n $ \f e -> (mapVars   f . mapVars   f) e == mapVars   (mapVars   f . f) e
  , holds n $ \f e -> (mapConsts f . mapConsts f) e == mapConsts (mapConsts f . f) e

  -- the following do not hold in general:
  , exists n $ \f e -> values (mapValues f e) /= map f (values e)
  , exists n $ \f e -> vars   (mapVars   f e) /= map f (vars   e)
  , exists n $ \f e -> consts (mapConsts f e) /= map f (consts e)

  -- what actually holds is this:
  , holds n $ \f e -> values (mapValues f e) == concatMap (values . f) (values e)
  , holds n $ \f e -> vars   (mapVars   f e) == concatMap (vars   . f) (vars   e)
  , holds n $ \f e -> consts (mapConsts f e) == concatMap (consts . f) (consts e)

  -- tests of // and //-
  , ((xx -*- yy) -+- (yy -*- zz)) // [(xx,ii),(yy,jj),(zz,kk)] ==
    (ii -*- jj) -+- (jj -*- kk)

  , ((xx -*- yy) -+- (yy -*- zz)) //- [(xx,ii),(yy,jj),(zz,kk)] ==
    (ii -*- jj) -+- (jj -*- kk)

  , ((xx -*- yy) -+- (yy -*- zz)) // [(xx -*- yy,ii),(yy -*- zz,jj)] ==
    ii -+- jj

  , ((xx -*- yy) -+- (yy -*- zz)) //- [(xx -*- yy,ii),(yy -*- zz,jj)] ==
    (xx -*- yy) -+- (yy -*- zz)


  , ((xx -+- yy) -+- (yy -+- zz)) // [(yy,yy -+- zz)]
    == (xx -+- (yy -+- zz)) -+- ((yy -+- zz) -+- zz)

  , ((xx -+- yy) -+- (yy -+- zz)) //- [(yy,yy -+- zz)]
    == (xx -+- (yy -+- zz)) -+- ((yy -+- zz) -+- zz)

  , (xx -+- yy) // [(yy,yy -+- zz),(xx,xx -+- yy)]
    == (xx -+- yy) -+- (yy -+- zz)

  , (xx -+- yy) //- [(yy,yy -+- zz),(xx,xx -+- yy)]
    == (xx -+- yy) -+- (yy -+- zz)

  , ((xx -+- yy) -+- zz) // [(xx -+- yy, zero)] == (zero -+- zz)
  , (xx -+- (yy -+- zz)) // [(xx -+- yy, zero)] == (xx -+- (yy -+- zz))

  , holds n $ \(SameTypeE e1 e2)   ->          e1 // [(e1,e2)] == e2
  , holds n $ \(IntE e1) (IntE e2) -> (e1 -+- e1) // [(e1,e2)] == (e2 -+- e2)

  , holds n $ \e -> renameVarsBy id e == e
  , holds n $ \c e -> (renameVarsBy tail . renameVarsBy (c:)) e == e
  , renameVarsBy (++ "1") (xx -+- yy) == (var "x1" int -+- var "y1" int)
  , renameVarsBy (\(c:cs) -> succ c:cs) ((xx -+- yy) -+- ord' cc)
                                 == ((yy -+- zz) -+- ord' dd)
  ]

mapFst :: (a -> c) -> (a,b) -> (c,b)
mapFst f (x,y) = (f x, y)