File: Monad_Test.hs

package info (click to toggle)
haskell-equivalence 0.4.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 104 kB
  • sloc: haskell: 533; makefile: 7
file content (191 lines) | stat: -rw-r--r-- 4,582 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes, TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Data.Equivalence.Monad_Test where

import Test.QuickCheck hiding ((===), classes)

import Data.Equivalence.Monad

import Control.Monad
import Data.Function (on)
import Data.Set (Set)
import qualified Data.Set as Set
import System.Exit

--------------------------------------------------------------------------------
-- Test Suits
--------------------------------------------------------------------------------

-- run :: (Ord a) => STT s Identity (Equiv s (Set a) a)
run :: (Ord v) => (forall s. EquivM s (Set v) v a) -> a
run = runEquivM Set.singleton Set.union

runInt :: (forall s. EquivM s (Set Int) Int a) -> a
runInt = run

allM f l = liftM and $ mapM f l

getClasses l1 = mapM getClass l1

infixr 9 <.>

-- | Composition: pure function after functorial (monadic) function.
(<.>) :: Functor m => (b -> c) -> (a -> m b) -> a -> m c
(f <.> g) a = f <$> g a


--------------------------------------------------------------------------------
-- Properties
--------------------------------------------------------------------------------

prop_singleton v = runInt $ do
  d <- classDesc v
  return (d == Set.singleton v)

prop_equateAll l' v = runInt $ do
  let l = v:l'
  equateAll l
  d <- classDesc v
  return (d == Set.fromList l)

prop_combineAll l' v = runInt $ do
  let l = v:l'
  cls <- getClasses l
  cl <- getClass v
  combineAll cls
  d <- desc cl
  return (d == Set.fromList l)

prop_equate x y = runInt $ do
  equate x y
  d <- classDesc x
  return (d == Set.fromList [x,y])

prop_combine x y = runInt $ do
  [cx,cy] <- getClasses [x,y]
  combine cx cy
  d <- desc cx
  return (d == Set.fromList [x,y])

prop_equateOverlap x y z = runInt $ do
  equate x y
  equate y z
  equivalent x z

prop_combineOverlap x y z = runInt $ do
  [cx,cy,cz] <- getClasses [x,y,z]
  combine cx cy
  combine cy cz
  cx === cz

prop_equateAllOverlap x y l1' l2' = runInt $ do
  let l1 = x:l1'
      l2 = y:l2'
  equateAll l1
  equateAll l2
  if Set.null $ Set.fromList l1 `Set.intersection` Set.fromList l2
    then liftM not $ equivalent x y
    else equivalent x y

prop_combineAllOverlap x y l1' l2' = runInt $ do
  let l1 = x:l1'
      l2 = y:l2'
  cls1 <- getClasses l1
  cls2 <- getClasses l2
  [cx,cy] <- getClasses [x,y]
  combineAll cls1
  combineAll cls2
  if Set.null $ Set.fromList l1 `Set.intersection` Set.fromList l2
    then liftM not (cx === cy)
    else cx === cy

prop_removeClass x l' = runInt $ do
  let l = x:l'
  equateAll l
  removeClass x
  allM (\e -> liftM (== Set.singleton e) (classDesc e)) l

prop_remove x l' = runInt $ do
  let l = x:l'
  cls <- getClasses l
  combineAll cls
  cx <- getClass x
  remove cx
  allM check l
      where check e = liftM (== Set.singleton e) $ getClass e >>= desc

prop_removeClass' x y l1' l2' = runInt $ do
  let l1 = x:l1'
      l2 = x:y:l2'
  equateAll l1
  removeClass x
  equateAll l2
  d <- classDesc y
  return (Set.fromList l2 == d)

prop_remove' x y l1' l2' = runInt $ do
  let l1 = x:l1'
      l2 = x:y:l2'
  cls1 <- getClasses l1
  cls2 <- getClasses l2
  cx <- getClass x
  combineAll cls1
  remove cx
  combineAll cls2
  cy <- getClass y
  d <- desc cy
  return (Set.fromList l2 == d)


prop_getClasses l1 l1' l2 x y =
  putStrLn (show el ++ ";" ++ show cl) `whenFail` (el == cl)
  where
    l3 = concat (l2 : l1)

    el = runInt $ do
      mapM equateAll l1
      mapM removeClass l2
      mapM equateAll (l1' :: [[Int]])
      res <- mapM classDesc l3
      eq <- equivalent x y
      return (res,eq)

    cl = runInt $ do
      cls1 <- mapM getClasses l1
      mapM combineAll cls1
      cls2 <- getClasses l2
      mapM remove cls2
      cls1' <- mapM getClasses l1'
      mapM combineAll cls1'
      cls3 <- getClasses l3
      res <- mapM desc cls3
      [cx,cy] <- getClasses [x,y]
      eq <- cx === cy
      return (res,eq)

prop_values l = runInt $ do
    mapM (\x -> equate x x) l
    sameSet l <$> values
  where
    sameSet = (==) `on` Set.fromList

prop_classes l = runInt $ do
    mapM equateAll (l :: [[Int]])
    classes1 <- uniqClass =<< mapM getClass =<< values
    sameClasses classes1 =<< classes
  where
    uniqClass []     = return []
    uniqClass (c:cs) = (c :) <$> do
      uniqClass =<< filterM (not <.> (c ===)) cs

    sameClasses []       cs2 = return $ null cs2
    sameClasses (c:cs1') cs2 = sameClasses cs1' =<< filterM (not <.> (c ===)) cs2

return []

main :: IO ()
main = do
  success <- $quickCheckAll
  if success then exitSuccess else exitFailure