dimensions-0.1.0.0: test/Numeric/Dimensions/ListTest.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MagicHash #-}
-----------------------------------------------------------------------------
-- |
-- Module : Numeric.Dimensions.ListTest
-- Copyright : (c) Artem Chirkin
-- License : BSD3
--
-- Maintainer : chirkin@arch.ethz.ch
--
-- Testing type-level Lists and the inference plugin
--
-----------------------------------------------------------------------------
module Numeric.Dimensions.ListTest (runTests) where
import Test.QuickCheck (quickCheckAll)
import Numeric.TypeLits
import Numeric.Dimensions
-- * Test simple binary nat ops
natSum :: Dim a -> Dim b -> Proxy (a+b)
natSum _ _ = Proxy
natMul :: Dim a -> Dim b -> Proxy (a*b)
natMul _ _ = Proxy
natRem :: Dim a -> Dim b -> Proxy (a-b)
natRem _ _ = Proxy
natSucc :: Dim a -> Proxy (a + 1)
natSucc _ = Proxy
natPred :: Dim a -> Proxy (a - 1)
natPred _ = Proxy
prop_KnownNats :: Int -> Int -> Bool
prop_KnownNats a b
| x <- max (abs a) (abs b)
, y <- min (abs a) (abs b)
, z <- y `mod` 50
, Just (SomeDim (px@Dn :: Dim x)) <- someDimVal x
, Just (SomeDim (py@Dn :: Dim y)) <- someDimVal y
, Just (SomeDim (px1@Dn :: Dim x1)) <- someDimVal (x+1)
, Just (SomeDim (Dn :: Dim z)) <- someDimVal z
, Just Evidence <- (\e1 e2 e3 -> e1 `sumEvs` e2 `sumEvs` e3)
<$> inferMinusKnownDimM @x @y
<*> inferMinusKnownDimM @x1 @1
<*> Just ( inferPlusKnownDim @x @y
`sumEvs` inferTimesKnownDim @x @y
`sumEvs` inferPlusKnownDim @y @1
)
= and
[ x + y == intNatVal (natSum px py)
, x * y == intNatVal (natMul px py)
, x - y == intNatVal (natRem px py)
, x == intNatVal (natPred px1)
, y + 1 == intNatVal (natSucc py)
]
prop_KnownNats _ _ = True
-- * Test props on a single type-level list
prop_FiniteList :: Int -> [Int] -> Bool
prop_FiniteList a xs'
| n <- (abs a)
, xs <- (2+) . abs <$> xs'
, Just (SomeDim (Dn :: Dim n)) <- someDimVal n
, Just (SomeDims (pxs :: Dim xs)) <- someDimsVal xs
, Evidence <- reifyDimensions pxs
, Evidence <- inferDimFiniteList @xs
= and [ order @_ @xs == length xs
, case inferTakeNFiniteList @n @xs of
Evidence -> order @_ @(Take n xs) == length (take n xs)
, case inferDropNFiniteList @n @xs of
Evidence -> order @_ @(Drop n xs) == length (drop n xs)
, case inferReverseFiniteList @xs of
Evidence -> order @_ @(Reverse xs) == length (reverse xs)
]
prop_FiniteList _ _ = False
-- * Inference properties
prop_ListInference :: [Int] -> [Int] -> Bool
prop_ListInference xs' ys'
| xs <- (2+) . abs <$> xs'
, ys <- (2+) . abs <$> ys'
, Just (SomeDims (dxs :: Dim xs)) <- someDimsVal xs
, Just (SomeDims (dys :: Dim ys)) <- someDimsVal ys
, Evidence <- reifyDimensions dxs
, Evidence <- reifyDimensions dys
, Evidence <- inferDimFiniteList @xs
`sumEvs` inferDimFiniteList @ys
= and [ case inferConcatFiniteList @xs @ys of
Evidence -> order @_ @(xs ++ ys) == length xs + length ys
, case inferConcat @xs @ys `sumEvs`
inferConcatFiniteList @xs @ys of
Evidence -> case inferPrefixFiniteList @ys @(xs ++ ys) of
Evidence -> order @_ @(Prefix ys (xs ++ ys)) == length xs
, case inferConcat @xs @ys `sumEvs`
inferConcatFiniteList @xs @ys of
Evidence -> case inferSuffixFiniteList @xs @(xs ++ ys) of
Evidence -> order @_ @(Suffix xs (xs ++ ys)) == length ys
]
prop_ListInference _ _ = False
return []
runTests :: IO Bool
runTests = $quickCheckAll