diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..aab60a0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,91 @@ +name: CI + +# Trigger the workflow on push or pull request, but only for the master branch +on: + pull_request: + push: + branches: [master] + +jobs: + cabal: + name: ${{ matrix.os }} / ghc ${{ matrix.ghc }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macOS-latest, windows-latest] + cabal: ["3.2"] + ghc: + - "8.6.5" + - "8.8.3" + - "8.10.1" + exclude: + - os: macOS-latest + ghc: 8.8.3 + - os: macOS-latest + ghc: 8.6.5 + - os: windows-latest + ghc: 8.8.3 + - os: windows-latest + ghc: 8.6.5 + + steps: + - uses: actions/checkout@v2 + if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master' + + - uses: actions/setup-haskell@v1.1.1 + id: setup-haskell-cabal + name: Setup Haskell + with: + ghc-version: ${{ matrix.ghc }} + cabal-version: ${{ matrix.cabal }} + + - name: Freeze + run: | + cabal freeze + + - uses: actions/cache@v1 + name: Cache ~/.cabal/store + with: + path: ${{ steps.setup-haskell-cabal.outputs.cabal-store }} + key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }} + + - name: Build + run: | + cabal configure --enable-tests --enable-benchmarks --test-show-details=direct + cabal build all --disable-optimization + + - name: Test + run: | + cabal test all + + stack: + name: stack / ghc ${{ matrix.ghc }} + runs-on: ubuntu-latest + strategy: + matrix: + stack: ["2.3.1"] + ghc: ["8.8.3"] + + steps: + - uses: actions/checkout@v2 + if: github.event.action == 'opened' || github.event.action == 'synchronize' || github.event.ref == 'refs/heads/master' + + - uses: actions/setup-haskell@v1.1 + name: Setup Haskell Stack + with: + ghc-version: ${{ matrix.ghc }} + stack-version: ${{ matrix.stack }} + + - uses: actions/cache@v1 + name: Cache ~/.stack + with: + path: ~/.stack + key: ${{ runner.os }}-${{ matrix.ghc }}-stack + + - name: Build + run: | + stack build --system-ghc --test --bench --fast --no-run-tests --no-run-benchmarks + + - name: Test + run: | + stack test --system-ghc diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3378907..0000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: haskell -ghc: - - "8.8" - - "8.6" - - "8.4" diff --git a/Data/Row/Dictionaries.hs b/Data/Row/Dictionaries.hs index 3d082f2..c62a7e9 100644 --- a/Data/Row/Dictionaries.hs +++ b/Data/Row/Dictionaries.hs @@ -30,6 +30,9 @@ module Data.Row.Dictionaries , mapForall , IsA(..) , As(..) + , ActsOn(..) + , As'(..) + , apSingleForall -- * Re-exports , Dict(..), (:-)(..), HasDict(..), (\\), withDict ) @@ -58,9 +61,22 @@ class IsA c f a where instance c a => IsA c f (f a) where as = As +data As' c t a where + As' :: forall c f a t. (a ~ f t, c f) => As' c t a + +class ActsOn c t a where + actsOn :: As' c t a + +instance c f => ActsOn c t (f t) where + actsOn = As' + -- | An internal type used by the 'metamorph' in 'mapForall'. newtype MapForall c f (r :: Row k) = MapForall { unMapForall :: Dict (Forall (Map f r) (IsA c f)) } +-- | An internal type used by the 'metamorph' in 'apSingleForall'. +newtype ApSingleForall c a (fs :: Row (k -> k')) = ApSingleForall + { unApSingleForall :: Dict (Forall (ApSingle fs a) (ActsOn c a)) } + -- | This allows us to derive a `Forall (Map f r) ..` from a `Forall r ..`. mapForall :: forall f c ρ. Forall ρ c :- Forall (Map f ρ) (IsA c f) mapForall = Sub $ unMapForall $ metamorph @_ @ρ @c @FlipConst @Proxy @(MapForall c f) @Proxy Proxy empty uncons cons $ Proxy @@ -74,6 +90,19 @@ mapForall = Sub $ unMapForall $ metamorph @_ @ρ @c @FlipConst @Proxy @(MapForal \\ mapExtendSwap @ℓ @τ @ρ @f \\ uniqueMap @(Extend ℓ τ ρ) @f +-- | This allows us to derive a `Forall (ApSingle f r) ..` from a `Forall f ..`. +apSingleForall :: forall a c fs. Forall fs c :- Forall (ApSingle fs a) (ActsOn c a) +apSingleForall = Sub $ unApSingleForall $ metamorph @_ @fs @c @FlipConst @Proxy @(ApSingleForall c a) @Proxy Proxy empty uncons cons $ Proxy + where empty _ = ApSingleForall Dict + uncons _ _ = FlipConst Proxy + cons :: forall ℓ τ ρ. (KnownSymbol ℓ, c τ, FrontExtends ℓ τ ρ, AllUniqueLabels (Extend ℓ τ ρ)) + => Label ℓ -> FlipConst (Proxy τ) (ApSingleForall c a ρ) + -> ApSingleForall c a (Extend ℓ τ ρ) + cons _ (FlipConst (ApSingleForall Dict)) = case frontExtendsDict @ℓ @τ @ρ of + FrontExtendsDict Dict -> ApSingleForall Dict + \\ apSingleExtendSwap @ℓ @a @ρ @τ + \\ uniqueApSingle @(Extend ℓ τ ρ) @a + -- | Allow any 'Forall` over a row-type, be usable for 'Unconstrained1'. freeForall :: forall r c. Forall r c :- Forall r Unconstrained1 freeForall = Sub $ UNSAFE.unsafeCoerce @(Dict (Forall r c)) Dict @@ -102,11 +131,11 @@ mapExtendSwap :: forall ℓ τ r f. Dict (Extend ℓ (f τ) (Map f r) ≈ Map f mapExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained -- | Proof that the 'Ap' type family preserves labels and their ordering. -apExtendSwap :: forall ℓ (τ :: k) r (f :: k -> *) fs. Dict (Extend ℓ (f τ) (Ap fs r) ≈ Ap (Extend ℓ f fs) (Extend ℓ τ r)) +apExtendSwap :: forall ℓ τ r f fs. Dict (Extend ℓ (f τ) (Ap fs r) ≈ Ap (Extend ℓ f fs) (Extend ℓ τ r)) apExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained -- | Proof that the 'ApSingle' type family preserves labels and their ordering. -apSingleExtendSwap :: forall k ℓ (τ :: k) r (f :: k -> *). Dict (Extend ℓ (f τ) (ApSingle r τ) ≈ ApSingle (Extend ℓ f r) τ) +apSingleExtendSwap :: forall ℓ τ r f. Dict (Extend ℓ (f τ) (ApSingle r τ) ≈ ApSingle (Extend ℓ f r) τ) apSingleExtendSwap = UNSAFE.unsafeCoerce $ Dict @Unconstrained -- | Proof that the 'Ap' type family preserves labels and their ordering. diff --git a/Data/Row/Records.hs b/Data/Row/Records.hs index 97d2d70..71a594c 100644 --- a/Data/Row/Records.hs +++ b/Data/Row/Records.hs @@ -351,7 +351,7 @@ mapF f = unRFMap . biMetamorph @_ @_ @ϕ @ρ @c @(,) @RecAp @(RFMap g) @App Prox => Label ℓ -> (App f τ, RFMap g ϕ ρ) -> RFMap g (Extend ℓ f ϕ) (Extend ℓ τ ρ) doCons l (App v, RFMap r) = RFMap (extend l (f @f @τ v) r) \\ mapExtendSwap @ℓ @τ @ρ @g - \\ apExtendSwap @_ @ℓ @(g τ) @(Map g ρ) @f @ϕ + \\ apExtendSwap @ℓ @(g τ) @(Map g ρ) @f @ϕ -- | A function to map over a record given no constraint. map' :: forall f r. FreeForall r => (forall a. a -> f a) -> Rec r -> Rec (Map f r) diff --git a/Data/Row/Variants.hs b/Data/Row/Variants.hs index cedc9c2..2f23a1f 100644 --- a/Data/Row/Variants.hs +++ b/Data/Row/Variants.hs @@ -52,7 +52,7 @@ module Data.Row.Variants -- ** Map , Map, map, map', transform, transform' -- ** Fold - , Forall, erase, eraseWithLabels, eraseZip + , Forall, erase, eraseWithLabels, eraseZipGeneral, eraseZip -- ** Sequence , sequence -- ** Compose @@ -109,14 +109,9 @@ instance Forall r Eq => Eq (Var r) where instance (Forall r Eq, Forall r Ord) => Ord (Var r) where compare :: Var r -> Var r -> Ordering - compare x y = getConst $ metamorph @_ @r @Ord @Either @(Product Var Var) @(Const Ordering) @(Const Ordering) Proxy doNil doUncons doCons (Pair x y) - where doNil (Pair x _) = impossible x - doUncons l (Pair r1 r2) = case (trial r1 l, trial r2 l) of - (Left a, Left b) -> Left $ Const $ compare a b - (Left _, Right _) -> Left $ Const LT - (Right _, Left _) -> Left $ Const GT - (Right x, Right y) -> Right $ Pair x y - doCons _ = Const . either getConst getConst + compare = eraseZipGeneral @Ord @r @Ordering @Text $ \case + (Left (_, x, y)) -> compare x y + (Right ((s1, _), (s2, _))) -> compare s1 s2 instance Forall r NFData => NFData (Var r) where rnf r = getConst $ metamorph @_ @r @NFData @Either @Var @(Const ()) @Identity Proxy empty doUncons doCons r @@ -240,18 +235,48 @@ eraseWithLabels f = getConst . metamorph @_ @ρ @c @Either @Var @(Const (s,b)) @ doCons l (Left (Identity x)) = Const (show' l, f x) doCons _ (Right (Const c)) = Const c --- | A fold over two row type structures at once + +data ErasedVal c s = forall y. c y => ErasedVal (s, y) +data ErasePair c s ρ = ErasePair (Either (ErasedVal c s) (Var ρ)) (Either (ErasedVal c s) (Var ρ)) + +-- | A fold over two variants at once. A call `eraseZipGeneral f x y` will return +-- `f (Left (show l, a, b))` when `x` and `y` both have values at the same label `l` +-- and will return `f (Right ((show l1, a), (show l2, b)))` when they have values +-- at different labels `l1` and `l2` respectively. +eraseZipGeneral + :: forall c ρ b s. (Forall ρ c, IsString s) + => (forall x y. (c x, c y) => Either (s, x, x) ((s, x), (s, y)) -> b) + -> Var ρ -> Var ρ -> b +eraseZipGeneral f x y = getConst $ metamorph @_ @ρ @c @Either @(ErasePair c s) @(Const b) @(Const b) Proxy doNil doUncons doCons (ErasePair (Right x) (Right y)) + where + doNil (ErasePair (Left (ErasedVal a)) (Left (ErasedVal b))) = + Const $ f $ Right (a, b) + doNil (ErasePair (Right x) _) = impossible x + doNil (ErasePair _ (Right y)) = impossible y + doUncons :: forall ℓ τ ρ. (KnownSymbol ℓ, c τ, HasType ℓ τ ρ) + => Label ℓ -> ErasePair c s ρ -> Either (Const b τ) (ErasePair c s (ρ .- ℓ)) + doUncons _ (ErasePair (Left (ErasedVal a)) (Left (ErasedVal b))) = + Left $ Const $ f $ Right (a, b) + doUncons l (ErasePair (Right x) (Left eb)) = case (trial x l, eb) of + (Left a, ErasedVal b) -> Left $ Const $ f $ Right ((show' l, a), b) + (Right x', _) -> Right $ ErasePair (Right x') (Left eb) + doUncons l (ErasePair (Left ea) (Right y)) = case (ea, trial y l) of + (ErasedVal a, Left b) -> Left $ Const $ f $ Right (a, (show' l, b)) + (_, Right x') -> Right $ ErasePair (Left ea) (Right x') + doUncons l (ErasePair (Right x) (Right y)) = case (trial x l, trial y l) of + (Left (a :: x), Left b) -> Left $ Const $ f @x @x $ Left (show' l, a, b) + (Left a, Right y') -> Right $ ErasePair (Left $ ErasedVal (show' l, a)) (Right y') + (Right x', Left b) -> Right $ ErasePair (Right x') (Left $ ErasedVal (show' l, b)) + (Right x', Right y') -> Right $ ErasePair (Right x') (Right y') + doCons _ (Left (Const b)) = Const b + doCons _ (Right (Const b)) = Const b + + +-- | A simpler fold over two variants at once eraseZip :: forall c ρ b. Forall ρ c => (forall a. c a => a -> a -> b) -> Var ρ -> Var ρ -> Maybe b -eraseZip f x y = getConst $ metamorph @_ @ρ @c @Either @(Product Var Var) @(Const (Maybe b)) @(Const (Maybe b)) Proxy doNil doUncons doCons (Pair x y) - where doNil _ = Const Nothing - doUncons :: forall ℓ τ ρ. (KnownSymbol ℓ, c τ, HasType ℓ τ ρ) - => Label ℓ -> Product Var Var ρ -> Either (Const (Maybe b) τ) (Product Var Var (ρ .- ℓ)) - doUncons l (Pair r1 r2) = case (trial r1 l, trial r2 l) of - (Left a, Left b) -> Left $ Const $ Just $ f a b - (Right x, Right y) -> Right $ Pair x y - _ -> Left $ Const Nothing - doCons _ (Left (Const c)) = Const c - doCons _ (Right (Const c)) = Const c +eraseZip f = eraseZipGeneral @c @ρ @(Maybe b) @Text $ \case + Left (_,x,y) -> Just (f x y) + _ -> Nothing -- | VMap is used internally as a type level lambda for defining variant maps. @@ -418,43 +443,24 @@ fromLabels mk = getCompose $ metamorph @_ @ρ @c @FlipConst @(Const ()) @(Compos newtype VApS x (fs :: Row (* -> *)) = VApS { unVApS :: Var (ApSingle fs x) } newtype FlipApp (x :: *) (f :: * -> *) = FlipApp (f x) +-- | A version of 'erase' that works even when the row-type of the variant argument +-- is of the form 'ApSingle fs x'. eraseSingle :: forall (c :: (* -> *) -> Constraint) (fs :: Row (* -> *)) (x :: *) (y :: *) - . (Forall fs c) + . Forall fs c => (forall f . (c f) => f x -> y) -> Var (ApSingle fs x) -> y -eraseSingle f = - getConst - . metamorph @_ @fs @c @Either @(VApS x) @(Const y) @(FlipApp x) - Proxy - doNil - doUncons - doCons - . VApS - where - doNil = impossible . unVApS - - doUncons - :: forall l f fs - . ( c f - , fs .! l ≈ f - , KnownSymbol l - ) - => Label l - -> VApS x fs - -> Either (FlipApp x f) (VApS x (fs .- l)) - doUncons l = (FlipApp +++ VApS) . (flip trial l \\ apSingleHas @fs @l @f @x) . unVApS - - doCons - :: forall l f fs - . (c f) - => Label l - -> Either (FlipApp x f) (Const y fs) - -> Const y (Extend l f fs) - doCons _ (Left (FlipApp v)) = Const (f v) - doCons _ (Right (Const y)) = Const y +eraseSingle f = erase @(ActsOn c x) @(ApSingle fs x) @y g + \\ apSingleForall @x @c @fs + where + g :: forall a. ActsOn c x a => a -> y + g a = case actsOn @c @x @a of As' -> f a +-- | Performs a functorial-like map over an 'ApSingle' variant. +-- In other words, it acts as a variant transformer to convert a variant of +-- @f x@ values to a variant of @f y@ values. If no constraint is needed, +-- instantiate the first type argument with 'Unconstrained1'. mapSingle :: forall (c :: (* -> *) -> Constraint) (fs :: Row (* -> *)) (x :: *) (y :: *) . (Forall fs c) @@ -473,15 +479,19 @@ mapSingle f = unVApS . metamorph @_ @fs @c @Either @(VApS x) @(VApS y) @(FlipApp . flip (trial \\ apSingleHas @fs @l @f @x) l . unVApS - doCons :: forall l f fs. (KnownSymbol l, c f) + doCons :: forall l f fs. (KnownSymbol l, c f, AllUniqueLabels (Extend l f fs)) => Label l -> Either (FlipApp x f) (VApS y fs) -> VApS y (Extend l f fs) - doCons (toKey -> l) (Left (FlipApp x)) = VApS . OneOf l . HideType $ f x - doCons l (Right (VApS v)) = VApS $ - extend @(f y) l v - \\ apSingleExtendSwap @_ @l @y @fs @f - + doCons l (Left (FlipApp x)) = VApS $ IsJust l (f x) + \\ apSingleExtendSwap @l @y @fs @f + \\ extendHas @(ApSingle fs y) @l @(f y) + \\ uniqueApSingle @(Extend l f fs) @y + doCons l (Right (VApS v)) = VApS $ extend @(f y) l v + \\ apSingleExtendSwap @l @y @fs @f + +-- | A version of 'eraseZip' that works even when the row-types of the variant +-- arguments are of the form 'ApSingle fs x'. eraseZipSingle :: forall c fs (x :: *) (y :: *) z . (Forall fs c) => (forall f. c f => f x -> f y -> z) diff --git a/benchmarks/perf/Main.hs b/benchmarks/perf/Main.hs index 7d2d8f0..ea05b1a 100644 --- a/benchmarks/perf/Main.hs +++ b/benchmarks/perf/Main.hs @@ -1,6 +1,6 @@ module Main (main) where -import Criterion.Main +import Gauge.Main import Data.String @@ -20,42 +20,42 @@ type SixteenRecord a = .+ "i20" .== a .+ "i21" .== a .+ "i22" .== a .+ "i23" .== a .+ "i30" .== a .+ "i31" .== a .+ "i32" .== a .+ "i33" .== a -type SixtyFourRecord a = - "i0" .== a .+ "i1" .== a .+ "i2" .== a .+ "i3" .== a - .+ "i10" .== a .+ "i11" .== a .+ "i12" .== a .+ "i13" .== a - .+ "i20" .== a .+ "i21" .== a .+ "i22" .== a .+ "i23" .== a - .+ "i30" .== a .+ "i31" .== a .+ "i32" .== a .+ "i33" .== a - .+ "i100" .== a .+ "i101" .== a .+ "i102" .== a .+ "i103" .== a - .+ "i110" .== a .+ "i111" .== a .+ "i112" .== a .+ "i113" .== a - .+ "i120" .== a .+ "i121" .== a .+ "i122" .== a .+ "i123" .== a - .+ "i130" .== a .+ "i131" .== a .+ "i132" .== a .+ "i133" .== a - .+ "i200" .== a .+ "i201" .== a .+ "i202" .== a .+ "i203" .== a - .+ "i210" .== a .+ "i211" .== a .+ "i212" .== a .+ "i213" .== a - .+ "i220" .== a .+ "i221" .== a .+ "i222" .== a .+ "i223" .== a - .+ "i230" .== a .+ "i231" .== a .+ "i232" .== a .+ "i233" .== a - .+ "i300" .== a .+ "i301" .== a .+ "i302" .== a .+ "i303" .== a - .+ "i310" .== a .+ "i311" .== a .+ "i312" .== a .+ "i313" .== a - .+ "i320" .== a .+ "i321" .== a .+ "i322" .== a .+ "i323" .== a - .+ "i330" .== a .+ "i331" .== a .+ "i332" .== a .+ "i333" .== a +-- type SixtyFourRecord a = +-- "i0" .== a .+ "i1" .== a .+ "i2" .== a .+ "i3" .== a +-- .+ "i10" .== a .+ "i11" .== a .+ "i12" .== a .+ "i13" .== a +-- .+ "i20" .== a .+ "i21" .== a .+ "i22" .== a .+ "i23" .== a +-- .+ "i30" .== a .+ "i31" .== a .+ "i32" .== a .+ "i33" .== a +-- .+ "i100" .== a .+ "i101" .== a .+ "i102" .== a .+ "i103" .== a +-- .+ "i110" .== a .+ "i111" .== a .+ "i112" .== a .+ "i113" .== a +-- .+ "i120" .== a .+ "i121" .== a .+ "i122" .== a .+ "i123" .== a +-- .+ "i130" .== a .+ "i131" .== a .+ "i132" .== a .+ "i133" .== a +-- .+ "i200" .== a .+ "i201" .== a .+ "i202" .== a .+ "i203" .== a +-- .+ "i210" .== a .+ "i211" .== a .+ "i212" .== a .+ "i213" .== a +-- .+ "i220" .== a .+ "i221" .== a .+ "i222" .== a .+ "i223" .== a +-- .+ "i230" .== a .+ "i231" .== a .+ "i232" .== a .+ "i233" .== a +-- .+ "i300" .== a .+ "i301" .== a .+ "i302" .== a .+ "i303" .== a +-- .+ "i310" .== a .+ "i311" .== a .+ "i312" .== a .+ "i313" .== a +-- .+ "i320" .== a .+ "i321" .== a .+ "i322" .== a .+ "i323" .== a +-- .+ "i330" .== a .+ "i331" .== a .+ "i332" .== a .+ "i333" .== a -my64Record :: Rec (SixtyFourRecord Double) -my64Record = - #i0 .== 0 .+ #i1 .== 0 .+ #i2 .== 0 .+ #i3 .== 0 - .+ #i10 .== 0 .+ #i11 .== 0 .+ #i12 .== 0 .+ #i13 .== 0 - .+ #i20 .== 0 .+ #i21 .== 0 .+ #i22 .== 0 .+ #i23 .== 0 - .+ #i30 .== 0 .+ #i31 .== 0 .+ #i32 .== 0 .+ #i33 .== 0 - .+ #i100 .== 0 .+ #i101 .== 0 .+ #i102 .== 0 .+ #i103 .== 0 - .+ #i110 .== 0 .+ #i111 .== 0 .+ #i112 .== 0 .+ #i113 .== 0 - .+ #i120 .== 0 .+ #i121 .== 0 .+ #i122 .== 0 .+ #i123 .== 0 - .+ #i130 .== 0 .+ #i131 .== 0 .+ #i132 .== 0 .+ #i133 .== 0 - .+ #i200 .== 0 .+ #i201 .== 0 .+ #i202 .== 0 .+ #i203 .== 0 - .+ #i210 .== 0 .+ #i211 .== 0 .+ #i212 .== 0 .+ #i213 .== 0 - .+ #i220 .== 0 .+ #i221 .== 0 .+ #i222 .== 0 .+ #i223 .== 0 - .+ #i230 .== 0 .+ #i231 .== 0 .+ #i232 .== 0 .+ #i233 .== 0 - .+ #i300 .== 0 .+ #i301 .== 0 .+ #i302 .== 0 .+ #i303 .== 0 - .+ #i310 .== 0 .+ #i311 .== 0 .+ #i312 .== 0 .+ #i313 .== 0 - .+ #i320 .== 0 .+ #i321 .== 0 .+ #i322 .== 0 .+ #i323 .== 0 - .+ #i330 .== 0 .+ #i331 .== 0 .+ #i332 .== 0 .+ #i333 .== 0 +-- my64Record :: Rec (SixtyFourRecord Double) +-- my64Record = +-- #i0 .== 0 .+ #i1 .== 0 .+ #i2 .== 0 .+ #i3 .== 0 +-- .+ #i10 .== 0 .+ #i11 .== 0 .+ #i12 .== 0 .+ #i13 .== 0 +-- .+ #i20 .== 0 .+ #i21 .== 0 .+ #i22 .== 0 .+ #i23 .== 0 +-- .+ #i30 .== 0 .+ #i31 .== 0 .+ #i32 .== 0 .+ #i33 .== 0 +-- .+ #i100 .== 0 .+ #i101 .== 0 .+ #i102 .== 0 .+ #i103 .== 0 +-- .+ #i110 .== 0 .+ #i111 .== 0 .+ #i112 .== 0 .+ #i113 .== 0 +-- .+ #i120 .== 0 .+ #i121 .== 0 .+ #i122 .== 0 .+ #i123 .== 0 +-- .+ #i130 .== 0 .+ #i131 .== 0 .+ #i132 .== 0 .+ #i133 .== 0 +-- .+ #i200 .== 0 .+ #i201 .== 0 .+ #i202 .== 0 .+ #i203 .== 0 +-- .+ #i210 .== 0 .+ #i211 .== 0 .+ #i212 .== 0 .+ #i213 .== 0 +-- .+ #i220 .== 0 .+ #i221 .== 0 .+ #i222 .== 0 .+ #i223 .== 0 +-- .+ #i230 .== 0 .+ #i231 .== 0 .+ #i232 .== 0 .+ #i233 .== 0 +-- .+ #i300 .== 0 .+ #i301 .== 0 .+ #i302 .== 0 .+ #i303 .== 0 +-- .+ #i310 .== 0 .+ #i311 .== 0 .+ #i312 .== 0 .+ #i313 .== 0 +-- .+ #i320 .== 0 .+ #i321 .== 0 .+ #i322 .== 0 .+ #i323 .== 0 +-- .+ #i330 .== 0 .+ #i331 .== 0 .+ #i332 .== 0 .+ #i333 .== 0 main :: IO () main = @@ -70,9 +70,9 @@ main = , bench "recordFromLabels 11" $ nf id $ fromLabels @IsString @(ElevenRecord String) (fromString . show) , bench "default 16" $ nf id $ default' @Num @(SixteenRecord Double) 0 , bench "recordFromLabels 16" $ nf id $ fromLabels @IsString @(SixteenRecord String) (fromString . show) - , bench "simple 64" $ nf id $ my64Record - , bench "default 64" $ nf id $ default' @Num @(SixtyFourRecord Double) 0 - , bench "recordFromLabels 64" $ nf id $ fromLabels @IsString @(SixtyFourRecord String) (fromString . show) + -- , bench "simple 64" $ nf id $ my64Record + -- , bench "default 64" $ nf id $ default' @Num @(SixtyFourRecord Double) 0 + -- , bench "recordFromLabels 64" $ nf id $ fromLabels @IsString @(SixtyFourRecord String) (fromString . show) ] , bgroup "Record Append" [ bench "append 3 3" $ nf (uncurry (.+)) (#a .== () .+ #b .== () .+ #c .== (), #d .== () .+ #e .== () .+ #f .== ()) @@ -81,15 +81,15 @@ main = ] , bgroup "Record Access" [ bench "get 2 of 4" $ nf (.! #i1) $ default' @Num @(FourRecord Double) 0 - [ bench "get 7 of 11" $ nf (.! #i1) $ default' @Num @(ElevenRecord Double) 0 + , bench "get 7 of 11" $ nf (.! #i1) $ default' @Num @(ElevenRecord Double) 0 , bench "get 4 of 16" $ nf (.! #i10) $ default' @Num @(SixteenRecord Double) 0 , bench "get 16 of 16" $ nf (.! #i33) $ default' @Num @(SixteenRecord Double) 0 - , bench "get 4 of 64" $ nf (.! #i10) $ default' @Num @(SixtyFourRecord Double) 1 - , bench "get 45 of 64" $ nf (.! #i230) $ default' @Num @(SixtyFourRecord Double) 2 - , bench "get 63 of 64" $ nf (.! #i332) $ default' @Num @(SixtyFourRecord Double) 3 + -- , bench "get 4 of 64" $ nf (.! #i10) $ default' @Num @(SixtyFourRecord Double) 1 + -- , bench "get 45 of 64" $ nf (.! #i230) $ default' @Num @(SixtyFourRecord Double) 2 + -- , bench "get 63 of 64" $ nf (.! #i332) $ default' @Num @(SixtyFourRecord Double) 3 ] , bgroup "Record Metamorphosis" [ bench "erase 4" $ nf (erase @Show show) $ #a .== () .+ #b .== () .+ #c .== () .+ #d .== () - , bench "erase 64" $ nf (erase @Show show) $ my64Record + -- , bench "erase 64" $ nf (erase @Show show) $ my64Record ] ] diff --git a/row-types.cabal b/row-types.cabal index a236ff4..24c8fa8 100644 --- a/row-types.cabal +++ b/row-types.cabal @@ -7,7 +7,7 @@ Maintainer: dwincort@gmail.com homepage: https://github.com/target/row-types Build-Type: Simple Cabal-Version: >=1.10 -Tested-With: GHC == 8.4, GHC == 8.6, GHC == 8.8 +Tested-With: GHC == 8.6.5, GHC == 8.8.3, GHC == 8.10.1 Category: Data, Data Structures Synopsis: Open Records and Variants Description: @@ -29,7 +29,7 @@ extra-source-files: Library Build-Depends: base >= 2 && < 5, - constraints, + constraints >= 0.11, deepseq >= 1.4, hashable >= 1.2, unordered-containers >= 0.2, @@ -62,7 +62,7 @@ benchmark perf build-depends: base >= 2 && < 6 , row-types , deepseq >= 1.4 - , criterion >= 1.1 + , gauge >= 0.2.0 default-language: Haskell2010 default-extensions: AllowAmbiguousTypes, DataKinds, diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..67e4a02 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,68 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/yaml_configuration/ + +# Resolver to choose a 'specific' stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# resolver: lts-3.5 +# resolver: nightly-2015-09-21 +# resolver: ghc-7.10.2 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# resolver: ./custom-snapshot.yaml +# resolver: https://example.com/snapshots/2018-01-01.yaml +resolver: lts-14.27 + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the resolver. +# These entries can reference officially published versions as well as +# forks / in-progress versions pinned to a git hash. For example: +# +extra-deps: +- constraints-0.12@sha256:71c7999d7fa01d8941f08d37d4c107c6b1bcbd0306e234157557b9b096b7f1be,2217 +- type-equality-1@sha256:d36324583fbafc5698c3f898ccf7cf041cbf42435fc2559c28e8f77682739a8e,1517 +# - acme-missiles-0.3 +# - git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# +# extra-deps: [] + +# Override default flag values for local packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=2.3" +# +# Override the architecture used by stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..49f0037 --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,26 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: +- completed: + hackage: constraints-0.12@sha256:71c7999d7fa01d8941f08d37d4c107c6b1bcbd0306e234157557b9b096b7f1be,2217 + pantry-tree: + size: 867 + sha256: 40bb55ad831b213078b79f54bb09c5a2200433dc2a495814444593fb00112834 + original: + hackage: constraints-0.12@sha256:71c7999d7fa01d8941f08d37d4c107c6b1bcbd0306e234157557b9b096b7f1be,2217 +- completed: + hackage: type-equality-1@sha256:d36324583fbafc5698c3f898ccf7cf041cbf42435fc2559c28e8f77682739a8e,1517 + pantry-tree: + size: 313 + sha256: a28a53db7adaaf0d9b39d2b678f3c6d5c8b08e42cb2b5d37156ce5e568c98707 + original: + hackage: type-equality-1@sha256:d36324583fbafc5698c3f898ccf7cf041cbf42435fc2559c28e8f77682739a8e,1517 +snapshots: +- completed: + size: 524996 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/27.yaml + sha256: 7ea31a280c56bf36ff591a7397cc384d0dff622e7f9e4225b47d8980f019a0f0 + original: lts-14.27