on main help sign in
[#47] Add Eq instance to TypeRepMap using QuantifiedConstraints (#72)

* [#47] Add Eq instance to TypeRepMap using QuantifiedConstraints Resolves #47 * Fix tests on old GHCs

commit449d5973c1d0f8bf08e980041dac49744a05cf16 authorDmitrii Kovanikov <kovanikov@gmail.com> dateWed 27 Mar 2019, 19:25 (8 years ago) parent304900e
5 files changed+81−30
.travis.yml+3−3 CHANGELOG.md+13−7 src/Data/TypeRepMap/Internal.hs+51−19 test/Test/TypeRep/MapProperty.hs+13 typerep-map.cabal+1−1
.travis.yml+3−3
@@ -4,7 +4,7 @@ language: haskell
44git:
55 depth: 5
66
7−cabal: "2.0"
7+cabal: "2.4"
88
99cache:
1010 directories:
@@ -18,7 +18,7 @@ matrix:
1818 - ghc: 8.4.4
1919 - ghc: 8.6.3
2020
21− - ghc: 8.6.3
21+ - ghc: 8.6.4
2222 env: STACK_YAML="$TRAVIS_BUILD_DIR/stack.yaml"
2323
2424install:
@@ -35,7 +35,7 @@ install:
3535script:
3636 - |
3737 if [ -z "$STACK_YAML" ]; then
38− cabal new-test $ALLOWNEWER
38+ cabal new-test --enable-tests
3939 else
4040 stack build --system-ghc --test --bench --no-run-benchmarks --no-terminal --ghc-options=-Werror
4141 fi
CHANGELOG.md+13−7
@@ -1,16 +1,22 @@
1−Change log
2−==========
1+# Changelog
32
43`typerep-map` uses [PVP Versioning][1].
5−The change log is available [on GitHub][2].
4+The changelog is available [on GitHub][2].
65
7−# 0.3.1
6+## 0.3.2 — Mar 27, 2019
7+
8+* [#47](https://github.com/kowainik/typerep-map/issues/47):
9+ Add `Eq` instance for `TypeRepMap` using `-XQuantifiedConstraints`.
10+* [#70](https://github.com/kowainik/typerep-map/issues/70):
11+ Bump up to `dependent-sum-0.5`.
12+
13+## 0.3.1
814
915* [#64](https://github.com/kowainik/typerep-map/issues/64):
1016 Fix segfault in `toList`.
1117* Support GHC 8.4.4 and 8.6.3.
1218
13−# 0.3.0
19+## 0.3.0
1420
1521* [#46](https://github.com/kowainik/typerep-map/issues/46):
1622 Make `Show` instance for `TypeRepMap` show keys.
@@ -22,7 +28,7 @@ The change log is available [on GitHub][2].
2228 instead of `IntMap`.
2329
2430
25−# 0.2.0
31+## 0.2.0
2632
2733* [#43](https://github.com/kowainik/typerep-map/issues/43):
2834 Implement `IsList` instance for `TypeRepMap`.
@@ -32,7 +38,7 @@ The change log is available [on GitHub][2].
3238 Add `map` function for `TMap`.
3339* Drop support for `ghc-8.0.2`.
3440
35−# 0.1.0
41+## 0.1.0
3642
3743* Initially created.
3844
src/Data/TypeRepMap/Internal.hs+51−19
@@ -1,33 +1,40 @@
1−{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE BangPatterns #-}
3−{-# LANGUAGE DataKinds #-}
4−{-# LANGUAGE GADTs #-}
5−{-# LANGUAGE InstanceSigs #-}
6−{-# LANGUAGE KindSignatures #-}
7−{-# LANGUAGE MagicHash #-}
8−{-# LANGUAGE PolyKinds #-}
9−{-# LANGUAGE Rank2Types #-}
10−{-# LANGUAGE TypeFamilies #-}
11−{-# LANGUAGE TypeInType #-}
12−{-# LANGUAGE ViewPatterns #-}
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE BangPatterns #-}
3+{-# LANGUAGE CPP #-}
4+{-# LANGUAGE DataKinds #-}
5+{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE InstanceSigs #-}
7+{-# LANGUAGE KindSignatures #-}
8+{-# LANGUAGE MagicHash #-}
9+{-# LANGUAGE PolyKinds #-}
10+{-# LANGUAGE Rank2Types #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeInType #-}
13+{-# LANGUAGE ViewPatterns #-}
14+
15+#if __GLASGOW_HASKELL__ >= 806
16+{-# LANGUAGE QuantifiedConstraints #-}
17+#endif
1318
1419-- {-# OPTIONS_GHC -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes #-}
1520
16−-- | Internal API for 'TypeRepMap' and operations on it. The functions here do
17−-- not have any stability guarantees and can change between minor versions.
18−--
19−-- If you need to use this module for purposes other than tests,
20−-- create an issue.
21−--
21+{- | Internal API for 'TypeRepMap' and operations on it. The functions here do
22+not have any stability guarantees and can change between minor versions.
23+
24+If you need to use this module for purposes other than tests,
25+create an issue.
26+-}
27+
2228module Data.TypeRepMap.Internal where
2329
2430import Prelude hiding (lookup)
2531
32+import Control.DeepSeq
2633import Control.Monad.ST (ST, runST)
2734import Control.Monad.Zip (mzip)
28−import Control.DeepSeq
2935import Data.Function (on)
3036import Data.Kind (Type)
37+import Data.Type.Equality ((:~:) (..), TestEquality (..))
3138import Data.List (intercalate, nubBy)
3239import Data.Primitive.Array (Array, MutableArray, indexArray, mapArray', readArray, sizeofArray,
3340 thawArray, unsafeFreezeArray, writeArray)
@@ -97,6 +104,31 @@ instance Monoid (TypeRepMap f) where
97104 {-# INLINE mempty #-}
98105 {-# INLINE mappend #-}
99106
107+#if __GLASGOW_HASKELL__ >= 806
108+instance (forall a. Typeable a => Eq (f a)) => Eq (TypeRepMap f) where
109+ tm1 == tm2 = size tm1 == size tm2 && go 0
110+ where
111+ go :: Int -> Bool
112+ go i
113+ | i == size tm1 = True
114+ | otherwise = case testEquality tr1i tr2i of
115+ Nothing -> False
116+ Just Refl -> repEq tr1i (fromAny tv1i) (fromAny tv2i) && go (i + 1)
117+ where
118+ tr1i :: TypeRep x
119+ tr1i = anyToTypeRep $ indexArray (trKeys tm1) i
120+
121+ tr2i :: TypeRep y
122+ tr2i = anyToTypeRep $ indexArray (trKeys tm2) i
123+
124+ tv1i, tv2i :: Any
125+ tv1i = indexArray (trAnys tm1) i
126+ tv2i = indexArray (trAnys tm2) i
127+
128+ repEq :: TypeRep x -> f x -> f x -> Bool
129+ repEq tr = withTypeable tr (==)
130+#endif
131+
100132-- | Returns the list of 'Fingerprint's from 'TypeRepMap'.
101133toFingerprints :: TypeRepMap f -> [Fingerprint]
102134toFingerprints TypeRepMap{..} =
test/Test/TypeRep/MapProperty.hs+13
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DataKinds #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE KindSignatures #-}
@@ -65,6 +66,7 @@ test_DeleteMember = prop "member k . delete k == False" $ do
6566-- Semigroup and Monoid laws
6667----------------------------------------------------------------------------
6768
69+#if __GLASGOW_HASKELL__ < 806
6870-- This newtype is used to compare 'TypeRepMap's using only 'Fingerprint's. It's
6971-- not a good idea to write such `Eq` instance for `TypeRepMap` itself because
7072-- it doesn't compare values so it's not true equality. But this should be
@@ -75,18 +77,29 @@ newtype FpMap f = FpMap (TypeRepMap f)
7577instance Eq (FpMap f) where
7678 FpMap (TypeRepMap as1 bs1 _ _) == FpMap (TypeRepMap as2 bs2 _ _) =
7779 as1 == as2 && bs1 == bs2
80+#endif
7881
7982test_SemigroupAssoc :: PropertyTest
8083test_SemigroupAssoc = prop "x <> (y <> z) == (x <> y) <> z" $ do
84+#if __GLASGOW_HASKELL__ >= 806
85+ x <- forAll genMap
86+ y <- forAll genMap
87+ z <- forAll genMap
88+#else
8189 x <- FpMap <$> forAll genMap
8290 y <- FpMap <$> forAll genMap
8391 z <- FpMap <$> forAll genMap
92+#endif
8493
8594 (x <> (y <> z)) === ((x <> y) <> z)
8695
8796test_MonoidIdentity :: PropertyTest
8897test_MonoidIdentity = prop "x <> mempty == mempty <> x == x" $ do
98+#if __GLASGOW_HASKELL__ >= 806
99+ x <- forAll genMap
100+#else
89101 x <- FpMap <$> forAll genMap
102+#endif
90103
91104 x <> mempty === x
92105 mempty <> x === x
typerep-map.cabal+1−1
@@ -1,5 +1,5 @@
11name: typerep-map
2−version: 0.3.1
2+version: 0.3.2
33synopsis: Efficient implementation of a dependent map with types as keys
44description:
55 A dependent map from type representations to values of these types.