packages feed

unboxing-vector-0.1.0.0: test/Spec.hs

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
import Prelude
import Test.HUnit
import qualified Data.Vector.Unboxing as V
import qualified Data.Vector.Unboxed
import Data.Monoid (Sum(..))
import Data.MonoTraversable (ofold)
---
import TestTypeErrors
import Foo (Foo,mkFoo)
import Generic

testInt = TestCase $ do
  let v = V.fromList [2,-5,42] :: V.Vector Int
      w = Data.Vector.Unboxed.fromList [2,-5,42] :: Data.Vector.Unboxed.Vector Int
  assertEqual "to unboxed" w (V.toUnboxedVector v)
  assertEqual "from unboxed" v (V.fromUnboxedVector w)

newtype IntMod17 = IntMod17 Int
  deriving (Eq,Show)
--  deriving newtype VF.Unboxable

instance V.Unboxable IntMod17 where
  type Rep IntMod17 = Int

instance Num IntMod17 where
  IntMod17 x + IntMod17 y = IntMod17 ((x + y) `rem` 17)
  IntMod17 x - IntMod17 y = IntMod17 ((x - y) `mod` 17)
  IntMod17 x * IntMod17 y = IntMod17 ((x * y) `rem` 17)
  negate (IntMod17 x) = IntMod17 (negate x `mod` 17)
  fromInteger x = IntMod17 (fromIntegral (x `mod` 17))
  abs = undefined; signum = undefined

testIntMod17 = TestCase $ do
  let v = V.fromList [-3,-2,-1,0,1,2,3,4,5] :: V.Vector IntMod17
  assertEqual "construction" (V.fromList [14,15,16,0,1,2,3,4,5]) v
  assertEqual "sum" 9 (V.sum v) -- not 60
  assertEqual "coercion" (V.fromList [14,15,16,0,1,2,3,4,5] :: V.Vector Int) (V.coerceVector v) -- this is possible because the constructor of IntMod17 is visible here
  let vSum = V.coerceVector v :: V.Vector (Sum IntMod17)
  assertEqual "coercion and sum" (Sum 9) (ofold vSum)

newtype Baz = Baz Foo
  deriving (Eq,Show,V.Unboxable)

testBaz = TestCase $ do
  let foo :: V.Vector Foo
      foo = V.singleton mkFoo
      baz :: V.Vector Baz
      baz = V.singleton (Baz mkFoo)
  assertEqual "construction" (Baz mkFoo) (V.head baz)
  assertEqual "map 1" baz (V.map Baz foo)
  assertEqual "map 2" foo (V.map (\(Baz x) -> x) baz)
  assertEqual "coercion" baz (V.coerceVector foo)

-- We can make an unboxed vector of Foo, even though we don't have 'Coercible Int Foo' in scope.
testAbstractType = TestCase $ do
  let v = V.singleton mkFoo :: V.Vector Foo
  assertEqual "Foo" mkFoo (V.head v)
  assertEqual "coercion" mkFoo (getSum $ V.head (V.coerceVector v :: V.Vector (Sum Foo)))

tests = TestList [TestLabel "Basic features" testIntMod17
                 ,TestLabel "Conversion with Data.Vector.Unboxed" testInt
                 ,TestLabel "Test with abstract type" testAbstractType
                 ,TestLabel "Check for type errors" testTypeErrors
                 ,TestLabel "Test with generic 1" testComplexDouble
                 ,TestLabel "Test with generic 2" testBar
                 ,TestLabel "Test with GND" testBaz
                 ]

main = runTestTT tests