tower-0.1.0: test/test.hs
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE DataKinds #-}
module Main where
import Protolude hiding ((+),(-),(*),(/),zero,one,negate,recip,div,mod,rem,quot, Integral(..))
import Test.Tasty (TestName, TestTree, testGroup, defaultMain)
import Test.Tasty.QuickCheck
import Tower.Algebra
import Tower.VectorU
import Tower.VectorA
data LawArity a =
Unary (a -> Bool) |
Binary (a -> a -> Bool) |
Ternary (a -> a -> a -> Bool) |
Ornary (a -> a -> a -> a -> Bool) |
Uniary (a -> Property)
type Law a = (TestName, LawArity a)
testLawOf :: (Arbitrary a, Show a) => [a] -> Law a -> TestTree
testLawOf _ (name, Unary f) = testProperty name f
testLawOf _ (name, Binary f) = testProperty name f
testLawOf _ (name, Ternary f) = testProperty name f
testLawOf _ (name, Ornary f) = testProperty name f
testLawOf _ (name, Uniary f) = testProperty name f
tests :: TestTree
tests = testGroup "everything"
[ testGroup "Int - Additive" $ testLawOf ([]::[Int]) <$> additiveLaws
, testGroup "Int - Additive Group" $ testLawOf ([]::[Int]) <$> additiveGroupLaws
, testGroup "Int - Multiplicative" $ testLawOf ([]::[Int]) <$> multiplicativeLaws
, testGroup "Int - Distributive" $ testLawOf ([]::[Int]) <$> distributiveLaws
, testGroup "Int - Integral" $ testLawOf ([]::[Int]) <$> integralLaws
, testGroup "Float - Additive" $ testLawOf ([]::[Float]) <$> additiveFloatLaws
, testGroup "Float - Additive Group" $ testLawOf ([]::[Float]) <$> additiveGroupLaws
, testGroup "Float - Multiplicative" $ testLawOf ([]::[Float]) <$> multiplicativeFloatLaws
, testGroup "Float - MultiplicativeGroup" $ testLawOf ([]::[Float]) <$> fieldFloatLaws
, testGroup "Float - Distributive" $ testLawOf ([]::[Float]) <$> distributiveFloatLaws
, testGroup "UVector 5 Int - Additive" $ testLawOf ([]::[VectorU 5 Int]) <$> additiveLaws
, testGroup "VectorU 5 Int - Additive Group" $ testLawOf ([]::[VectorU 5 Int]) <$> additiveGroupLaws
, testGroup "VectorU 5 Int - Multiplicative" $ testLawOf ([]::[VectorU 5 Int]) <$> multiplicativeLaws
, testGroup "VectorU 5 Int - Distributive" $ testLawOf ([]::[VectorU 5 Int]) <$> distributiveLaws
-- , testGroup "VectorU 5 Int - Integral" $ testLawOf ([]::[VectorU 5 Int]) <$> integralLaws
, testGroup "VectorU 5 Float - Additive" $ testLawOf ([]::[VectorU 5 Float]) <$> additiveFloatLaws
, testGroup "VectorU 5 Float - Additive Group" $ testLawOf ([]::[VectorU 5 Float]) <$> additiveGroupLaws
, testGroup "VectorU 5 Float - Multiplicative" $ testLawOf ([]::[VectorU 5 Float]) <$> multiplicativeFloatLaws
, testGroup "VectorU 5 Float - MultiplicativeGroup" $ testLawOf ([]::[VectorU 5 Float]) <$> fieldFloatLaws
, testGroup "VectorU 5 Float - Distributive" $ testLawOf ([]::[VectorU 5 Float]) <$> distributiveFloatLaws
, testGroup "VectorA Int - Additive" $ testLawOf ([]::[VectorA 5 [] Int]) <$> additiveLaws
, testGroup "VectorA Int - Additive Group" $ testLawOf ([]::[VectorA 5 [] Int]) <$> additiveGroupLaws
, testGroup "VectorA Int - Multiplicative" $ testLawOf ([]::[VectorA 5 [] Int]) <$> multiplicativeLaws
, testGroup "VectorA Int - Distributive" $ testLawOf ([]::[VectorA 5 [] Int]) <$> distributiveLaws
]
main :: IO ()
main = defaultMain tests
additiveLaws ::
( Eq a
, Additive a
) => [Law a]
additiveLaws =
[ ("associative: a + b = b + a", Ternary (\a b c -> (a + b) + c == a + (b + c)))
, ("left id: zero + a = a", Unary (\a -> zero + a == a))
, ("right id: a + zero = a", Unary (\a -> a + zero == a))
, ("commutative: a + b == b + a", Binary (\a b -> a + b == b + a))
]
additiveFloatLaws ::
( Eq a
, Additive a
, Show a
, Arbitrary a
) => [Law a]
additiveFloatLaws =
[ ("associative: a + b = b + a", Uniary $ expectFailure . (\a b c -> (a + b) + c == a + (b + c)))
, ("left id: zero + a = a", Unary (\a -> zero + a == a))
, ("right id: a + zero = a", Unary (\a -> a + zero == a))
, ("commutative: a + b == b + a", Binary (\a b -> a + b == b + a))
]
additiveGroupLaws ::
( Eq a
, AdditiveGroup a
) => [Law a]
additiveGroupLaws =
[ ("minus: a - a = zero", Unary (\a -> (a - a) == zero))
, ("negate minus: negate a == zero - a", Unary (\a -> negate a == zero - a))
, ("negate cancel: negate a + a == zero", Unary (\a -> negate a + a == zero))
]
multiplicativeLaws ::
( Eq a
, Multiplicative a
) => [Law a]
multiplicativeLaws =
[ ("associative: a * b = b * a", Ternary (\a b c -> (a * b) * c == a * (b * c)))
, ("left id: one * a = a", Unary (\a -> one * a == a))
, ("right id: a * one = a", Unary (\a -> a * one == a))
, ("commutative: a * b == b * a", Binary (\a b -> a * b == b * a))
]
aboutEqual :: (AdditiveGroup a, Ord a) => a -> a -> a -> Bool
aboutEqual eps a b = a - b <= eps && b - a <= eps
multiplicativeFloatLaws ::
( Eq a
, Show a
, Arbitrary a
, Multiplicative a
) => [Law a]
multiplicativeFloatLaws =
[ ("associative: a * b = b * a", Uniary $ expectFailure . (\a b c -> (a * b) * c == a * (b * c)))
, ("left id: one * a = a", Unary (\a -> one * a == a))
, ("right id: a * one = a", Unary (\a -> a * one == a))
, ("commutative: a * b == b * a", Binary (\a b -> a * b == b * a))
]
fieldLaws ::
( Eq a
, MultiplicativeGroup a
, AdditiveGroup a
) => [Law a]
fieldLaws =
[ ("divide: a == zero || a / a = one", Unary (\a -> a == zero || (a / a) == one))
, ("recip divide: recip a == one / a", Unary (\a -> recip a == one / a))
, ("recip left: recip a * a == one", Unary (\a -> a == zero || recip a * a == one))
, ("recip right: a * recip a == one", Unary (\a -> a == zero || a * recip a == one))
]
fieldFloatLaws ::
( MultiplicativeGroup a
, AdditiveGroup a
, Eq a
) => [Law a]
fieldFloatLaws =
[ ("divide: a == zero || a / a == one", Uniary $ expectFailure . (\a -> a == zero || a / a == one))
, ("recip divide: recip a == one / a", Unary (\a -> recip a == one / a))
, ("recip left: recip a * a == one", Uniary $ expectFailure . (\a -> a == zero || recip a * a == one))
, ("recip right: a * recip a == one", Uniary $ expectFailure . (\a -> a == zero || a * recip a == one))
]
distributiveLaws ::
( Eq a
, Distributive a
, Multiplicative a
) => [Law a]
distributiveLaws =
[ ("annihilation: a * zero == zero", Unary (\a -> a * zero == zero))
, ("left distributivity: a * (b + c) == a * b + a * c", Ternary (\a b c -> a * (b + c) == a * b + a * c))
, ("right distributivity: (a + b) * c == a * c + b * c", Ternary (\a b c -> (a + b) * c == a * c + b * c))
]
distributiveFloatLaws ::
( Eq a
, Distributive a
, Multiplicative a
, Show a
, Arbitrary a
) => [Law a]
distributiveFloatLaws =
[ ("annihilation: a * zero == zero", Unary (\a -> a * zero == zero))
, ("left distributivity: a * (b + c) == a * b + a * c", Uniary $ expectFailure . (\a b c -> a * (b + c) == a * b + a * c))
, ("right distributivity: (a + b) * c == a * c + b * c", Uniary $ expectFailure . (\a b c -> (a + b) * c == a * c + b * c))
]
integralLaws ::
( Eq a
, Integral a
) => [Law a]
integralLaws =
[ ("integral divmod: b == zero || b * (a `div` b) + (a `mod` b) == a", Binary (\a b -> b == zero || b * (a `div` b) + (a `mod` b) == a))
]
todoLaws ::
( -- Eq a
-- , AdditiveModule s a
) => [Law a]
todoLaws =
[ -- (a1+a2) +. s == a1 +. a2 +. s
-- m2 s = s *. (m1 + m2) == s*.m1 + s*.m2
-- m s1 s2 = (s1+s2)*.m == s1*.m + s2*.m
-- s1 s2 = s1*.(s2*.m) == (s1*s2)*.m
-- m = 1 *. m == m
-- free modules
-- m1 m2 = m1.*.m2 == m2.*.m1
-- m1 m2 m3 = m1.*.(m2.*.m3) == (m1.*.m2).*.m3
-- m = m == m.*.ones
-- Banach
-- v1 v2 = size (v1 - v2) == distance v1 v2
-- v = isZero v || size (normalize v) == 1
-- Metric
-- v1 v2 = distance v1 v2 >= 0
-- v1 v2 = v1 == v2 == distance v1 v2 == 0
-- v1 v2 = distance v1 v2 == distance v2 v1
-- m1 m2 m3 = distance m1 m2 <= distance m1 m3 + distance m2 m3
-- && distance m1 m3 <= distance m1 m2 + distance m2 m3
-- && distance m2 m3 <= distance m1 m3 + distance m2 m1
]