{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wno-orphans #-}

module Test.VMap where

import qualified Data.List as List
import qualified Data.Map.Strict as Map
import Data.VMap as VMap
import Test.Common

type MapT = Map.Map Char Int

type VMapT = VMap VB VP Char Int

instance
  (Ord k, Vector kv k, Vector vv v, Arbitrary k, Arbitrary v) =>
  Arbitrary (VMap kv vv k v)
  where
  arbitrary :: Gen (VMap kv vv k v)
arbitrary =
    Map k v -> VMap kv vv k v
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
Map k v -> VMap kv vv k v
VMap.fromMap (Map k v -> VMap kv vv k v)
-> ([(k, v)] -> Map k v) -> [(k, v)] -> VMap kv vv k v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(k, v)] -> Map k v
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(k, v)] -> VMap kv vv k v)
-> Gen [(k, v)] -> Gen (VMap kv vv k v)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen [(k, v)]
forall a. Arbitrary a => Gen a
arbitrary

prop_Roundtrip :: (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip :: forall a. (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip VMapT -> a
to a -> VMapT
from VMapT
km = a -> VMapT
from (VMapT -> a
to VMapT
km) VMapT -> VMapT -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== VMapT
km

prop_AsMapTo ::
  (Show a, Eq a) => (VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo :: forall a.
(Show a, Eq a) =>
(VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo VMapT -> a
fromVM MapT -> a
fromM VMapT
vm = VMapT -> a
fromVM VMapT
vm a -> a -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== MapT -> a
fromM (VMapT -> MapT
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> Map k v
toMap VMapT
vm)

prop_AsMapFrom :: (a -> VMapT) -> (a -> MapT) -> a -> Property
prop_AsMapFrom :: forall a. (a -> VMapT) -> (a -> MapT) -> a -> Property
prop_AsMapFrom a -> VMapT
mkVMap a -> MapT
mkMap a
a = VMapT -> MapT
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> Map k v
toMap (a -> VMapT
mkVMap a
a) MapT -> MapT -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== a -> MapT
mkMap a
a

vMapTests :: TestTree
vMapTests :: TestTree
vMapTests =
  String -> [TestTree] -> TestTree
testGroup
    String
"VMap"
    [ String -> [TestTree] -> TestTree
testGroup
        String
"roundtrip"
        [ String -> (VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"to/fromAscDistinctList" ((VMapT -> Property) -> TestTree)
-> (VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$
            (VMapT -> [(Char, Int)])
-> ([(Char, Int)] -> VMapT) -> VMapT -> Property
forall a. (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip VMapT -> [(Char, Int)]
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> [(k, v)]
VMap.toAscList [(Char, Int)] -> VMapT
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromDistinctAscList
        , String -> (VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"to/fromAscList" ((VMapT -> Property) -> TestTree)
-> (VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ (VMapT -> [(Char, Int)])
-> ([(Char, Int)] -> VMapT) -> VMapT -> Property
forall a. (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip VMapT -> [(Char, Int)]
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> [(k, v)]
VMap.toAscList [(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Eq k, Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromAscList
        , String -> (VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"to/fromList" ((VMapT -> Property) -> TestTree)
-> (VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ (VMapT -> [(Char, Int)])
-> ([(Char, Int)] -> VMapT) -> VMapT -> Property
forall a. (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip VMapT -> [(Char, Int)]
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> [(k, v)]
VMap.toAscList [(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromList
        , String -> (VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"to/fromMap" ((VMapT -> Property) -> TestTree)
-> (VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ (VMapT -> MapT) -> (MapT -> VMapT) -> VMapT -> Property
forall a. (VMapT -> a) -> (a -> VMapT) -> VMapT -> Property
prop_Roundtrip VMapT -> MapT
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> Map k v
VMap.toMap MapT -> VMapT
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
Map k v -> VMap kv vv k v
VMap.fromMap
        ]
    , String -> [TestTree] -> TestTree
testGroup
        String
"asMap"
        [ String -> ([(Char, Int)] -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"fromList" (([(Char, Int)] -> Property) -> TestTree)
-> ([(Char, Int)] -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ ([(Char, Int)] -> VMapT)
-> ([(Char, Int)] -> MapT) -> [(Char, Int)] -> Property
forall a. (a -> VMapT) -> (a -> MapT) -> a -> Property
prop_AsMapFrom [(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromList [(Char, Int)] -> MapT
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
        , String
-> ([(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"fromAscListWithKey" (([(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
 -> TestTree)
-> ([(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
-> TestTree
forall a b. (a -> b) -> a -> b
$ \[(Char, Int)]
xs Fun (Char, Int, Int) Int
f ->
            ([(Char, Int)] -> VMapT)
-> ([(Char, Int)] -> MapT) -> [(Char, Int)] -> Property
forall a. (a -> VMapT) -> (a -> MapT) -> a -> Property
prop_AsMapFrom
              ((Char -> Int -> Int -> Int) -> [(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Eq k, Vector kv k, Vector vv v) =>
(k -> v -> v -> v) -> [(k, v)] -> VMap kv vv k v
VMap.fromAscListWithKey (Fun (Char, Int, Int) Int -> Char -> Int -> Int -> Int
forall a b c d. Fun (a, b, c) d -> a -> b -> c -> d
applyFun3 Fun (Char, Int, Int) Int
f))
              ((Char -> Int -> Int -> Int) -> [(Char, Int)] -> MapT
forall k a. Eq k => (k -> a -> a -> a) -> [(k, a)] -> Map k a
Map.fromAscListWithKey (Fun (Char, Int, Int) Int -> Char -> Int -> Int -> Int
forall a b c d. Fun (a, b, c) d -> a -> b -> c -> d
applyFun3 Fun (Char, Int, Int) Int
f))
              (((Char, Int) -> Char) -> [(Char, Int)] -> [(Char, Int)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
List.sortOn (Char, Int) -> Char
forall a b. (a, b) -> a
fst [(Char, Int)]
xs)
        , String
-> (Int -> [(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"fromAscListWithKeyN" ((Int -> [(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
 -> TestTree)
-> (Int -> [(Char, Int)] -> Fun (Char, Int, Int) Int -> Property)
-> TestTree
forall a b. (a -> b) -> a -> b
$ \Int
n [(Char, Int)]
xs Fun (Char, Int, Int) Int
f ->
            ([(Char, Int)] -> VMapT)
-> ([(Char, Int)] -> MapT) -> [(Char, Int)] -> Property
forall a. (a -> VMapT) -> (a -> MapT) -> a -> Property
prop_AsMapFrom
              (Int -> (Char -> Int -> Int -> Int) -> [(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Eq k, Vector kv k, Vector vv v) =>
Int -> (k -> v -> v -> v) -> [(k, v)] -> VMap kv vv k v
VMap.fromAscListWithKeyN Int
n (Fun (Char, Int, Int) Int -> Char -> Int -> Int -> Int
forall a b c d. Fun (a, b, c) d -> a -> b -> c -> d
applyFun3 Fun (Char, Int, Int) Int
f))
              ((Char -> Int -> Int -> Int) -> [(Char, Int)] -> MapT
forall k a. Eq k => (k -> a -> a -> a) -> [(k, a)] -> Map k a
Map.fromAscListWithKey (Fun (Char, Int, Int) Int -> Char -> Int -> Int -> Int
forall a b c d. Fun (a, b, c) d -> a -> b -> c -> d
applyFun3 Fun (Char, Int, Int) Int
f) ([(Char, Int)] -> MapT)
-> ([(Char, Int)] -> [(Char, Int)]) -> [(Char, Int)] -> MapT
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [(Char, Int)] -> [(Char, Int)]
forall a. Int -> [a] -> [a]
take Int
n)
              (((Char, Int) -> Char) -> [(Char, Int)] -> [(Char, Int)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
List.sortOn (Char, Int) -> Char
forall a b. (a, b) -> a
fst [(Char, Int)]
xs)
        , String -> (VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"toAscList" ((VMapT -> Property) -> TestTree)
-> (VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ (VMapT -> [(Char, Int)])
-> (MapT -> [(Char, Int)]) -> VMapT -> Property
forall a.
(Show a, Eq a) =>
(VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo VMapT -> [(Char, Int)]
forall (kv :: * -> *) k (vv :: * -> *) v.
(Vector kv k, Vector vv v) =>
VMap kv vv k v -> [(k, v)]
VMap.toAscList MapT -> [(Char, Int)]
forall k a. Map k a -> [(k, a)]
Map.toAscList
        , String -> (Fun (Char, Int) String -> VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"foldMapWithKey" ((Fun (Char, Int) String -> VMapT -> Property) -> TestTree)
-> (Fun (Char, Int) String -> VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ \Fun (Char, Int) String
f ->
            let f' :: Char -> Int -> String
f' Char
k Int
v = Fun (Char, Int) String -> Char -> Int -> String
forall a b c. Fun (a, b) c -> a -> b -> c
applyFun2 Fun (Char, Int) String
f Char
k Int
v :: String
             in (VMapT -> String) -> (MapT -> String) -> VMapT -> Property
forall a.
(Show a, Eq a) =>
(VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo ((Char -> Int -> String) -> VMapT -> String
forall (kv :: * -> *) k (vv :: * -> *) v m.
(Vector kv k, Vector vv v, Monoid m) =>
(k -> v -> m) -> VMap kv vv k v -> m
VMap.foldMapWithKey Char -> Int -> String
f') ((Char -> Int -> String) -> MapT -> String
forall m k a. Monoid m => (k -> a -> m) -> Map k a -> m
Map.foldMapWithKey Char -> Int -> String
f')
        , String -> (Char -> VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"lookup" ((Char -> VMapT -> Property) -> TestTree)
-> (Char -> VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ \Char
k -> (VMapT -> Maybe Int) -> (MapT -> Maybe Int) -> VMapT -> Property
forall a.
(Show a, Eq a) =>
(VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo (Char -> VMapT -> Maybe Int
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
k -> VMap kv vv k v -> Maybe v
VMap.lookup Char
k) (Char -> MapT -> Maybe Int
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Char
k)
        , String -> (Char -> Int -> [(Char, Int)] -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"lookup (existing)" ((Char -> Int -> [(Char, Int)] -> Property) -> TestTree)
-> (Char -> Int -> [(Char, Int)] -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ \Char
k Int
v [(Char, Int)]
xs ->
            let xs' :: [(Char, Int)]
xs' = [(Char, Int)]
xs [(Char, Int)] -> [(Char, Int)] -> [(Char, Int)]
forall a. Semigroup a => a -> a -> a
<> [(Char
k, Int
v)]
             in (Char -> VMapT -> Maybe Int
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
k -> VMap kv vv k v -> Maybe v
VMap.lookup Char
k ([(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromList [(Char, Int)]
xs' :: VMapT) Maybe Int -> Maybe Int -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int -> Maybe Int
forall a. a -> Maybe a
Just Int
v)
                  Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (Char -> MapT -> Maybe Int
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Char
k ([(Char, Int)] -> MapT
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Char, Int)]
xs' :: MapT) Maybe Int -> Maybe Int -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int -> Maybe Int
forall a. a -> Maybe a
Just Int
v)
        , String -> (Int -> Char -> VMapT -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"finsWithDefault" ((Int -> Char -> VMapT -> Property) -> TestTree)
-> (Int -> Char -> VMapT -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ \Int
d Char
k ->
            (VMapT -> Int) -> (MapT -> Int) -> VMapT -> Property
forall a.
(Show a, Eq a) =>
(VMapT -> a) -> (MapT -> a) -> VMapT -> Property
prop_AsMapTo (Int -> Char -> VMapT -> Int
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
v -> k -> VMap kv vv k v -> v
VMap.findWithDefault Int
d Char
k) (Int -> Char -> MapT -> Int
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault Int
d Char
k)
        , String -> (Char -> Int -> [(Char, Int)] -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"finsWithDefault (existing)" ((Char -> Int -> [(Char, Int)] -> Property) -> TestTree)
-> (Char -> Int -> [(Char, Int)] -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ \Char
k Int
v [(Char, Int)]
xs ->
            let xs' :: [(Char, Int)]
xs' = [(Char, Int)]
xs [(Char, Int)] -> [(Char, Int)] -> [(Char, Int)]
forall a. Semigroup a => a -> a -> a
<> [(Char
k, Int
v)]
             in (Int -> Char -> VMapT -> Int
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
v -> k -> VMap kv vv k v -> v
VMap.findWithDefault Int
forall a. HasCallStack => a
undefined Char
k ([(Char, Int)] -> VMapT
forall k (kv :: * -> *) (vv :: * -> *) v.
(Ord k, Vector kv k, Vector vv v) =>
[(k, v)] -> VMap kv vv k v
VMap.fromList [(Char, Int)]
xs' :: VMapT) Int -> Int -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int
v)
                  Property -> Property -> Property
forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (Int -> Char -> MapT -> Int
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault Int
forall a. HasCallStack => a
undefined Char
k ([(Char, Int)] -> MapT
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Char, Int)]
xs' :: MapT) Int -> Int -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== Int
v)
        ]
    , String -> [Laws] -> TestTree
testLawsGroup
        String
"classes"
        [ Proxy VMapT -> Laws
forall a. (Eq a, Arbitrary a, Show a) => Proxy a -> Laws
eqLaws (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @VMapT)
        , Proxy VMapT -> Laws
forall a.
(Semigroup a, Eq a, Arbitrary a, Show a) =>
Proxy a -> Laws
semigroupLaws (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @VMapT)
        , Proxy VMapT -> Laws
forall a. (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
monoidLaws (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @VMapT)
        , Proxy VMapT -> Laws
forall a.
(IsList a, Show a, Show (Item a), Arbitrary a, Arbitrary (Item a),
 Eq a) =>
Proxy a -> Laws
isListLaws (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @VMapT)
        ]
    ]