extensible 0.2.9 → 0.2.10
raw patch · 10 files changed
+126/−42 lines, 10 files
Files
- CHANGELOG.md +4/−0
- benchmarks/AtoZ.hs +33/−3
- benchmarks/membership.hs +5/−6
- examples/test.hs +7/−0
- extensible.cabal +1/−1
- src/Data/Extensible/Dictionary.hs +1/−1
- src/Data/Extensible/Inclusion.hs +3/−3
- src/Data/Extensible/Internal.hs +66/−13
- src/Data/Extensible/Internal/Rig.hs +2/−2
- src/Data/Extensible/Product.hs +4/−13
CHANGELOG.md view
@@ -1,3 +1,7 @@+0.2.10+-----------------------------------------------------+* Optimized `sector` (~2x)+ 0.2.9 ----------------------------------------------------- * Renamed `(<?~)` to `(<?!$)`
benchmarks/AtoZ.hs view
@@ -38,9 +38,39 @@ <% O 14 <% P 15 <% Q 16 <% R 17 <% S 18 <% T 19 <% U 20 <% V 21 <% W 22 <% X 23 <% Y 24 <% Z 25 <% Nil -tuple26 :: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z)-tuple26 = (A 0, B 1, C 2, D 3, E 4, F 5, G 6, H 7, I 8, J 9, K 10, L 11, M 12- , N 13, O 14, P 15, Q 16, R 17, S 18, T 19, U 20, V 21, W 22, X 23, Y 24, Z 25)+data Data26 = Data26+ { getA :: A+ , getB :: B+ , getC :: C+ , getD :: D+ , getE :: E+ , getF :: F+ , getG :: G+ , getH :: H+ , getI :: I+ , getJ :: J+ , getK :: K+ , getL :: L+ , getM :: M+ , getN :: N+ , getO :: O+ , getP :: P+ , getQ :: Q+ , getR :: R+ , getS :: S+ , getT :: T+ , getU :: U+ , getV :: V+ , getW :: W+ , getX :: X+ , getY :: Y+ , getZ :: Z+ }++data26 :: Data26+data26 = Data26 (A 0) (B 1) (C 2) (D 3) (E 4) (F 5) (G 6) (H 7) (I 8) (J 9) (K 10)+ (L 11) (M 12) (N 13) (O 14) (P 15) (Q 16) (R 17) (S 18) (T 19) (U 20) (V 21)+ (W 22) (X 23) (Y 24) (Z 25) hlist26 :: HList AtoZ hlist26 = A 0 `HCons` B 1 `HCons` C 2 `HCons` D 3 `HCons` E 4 `HCons` F 5 `HCons` G 6
benchmarks/membership.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE ViewPatterns, TypeOperators, GADTs, Rank2Types, ScopedTypeVariables #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances, PolyKinds, ViewPatterns, TypeFamilies, TypeOperators, GADTs, Rank2Types, ScopedTypeVariables, DataKinds #-} import Data.Extensible import Data.Extensible.Internal+import Data.Extensible.Internal.Rig import Control.Applicative import Criterion.Main import AtoZ@@ -43,7 +44,8 @@ main = defaultMain [ bgroup "product" [- bench "A" $ whnf (\(pluck -> A x) -> x) extensible26+ bench "Data" $ whnf (\(getZ -> Z x) -> x) data26+ , bench "A" $ whnf (\(pluck -> A x) -> x) extensible26 , bench "B" $ whnf (\(pluck -> B x) -> x) extensible26 , bench "C" $ whnf (\(pluck -> C x) -> x) extensible26 , bench "D" $ whnf (\(pluck -> D x) -> x) extensible26@@ -95,7 +97,6 @@ , bench "X" $ whnf (\(hOccursFst -> X x) -> x) hlist26 , bench "Y" $ whnf (\(hOccursFst -> Y x) -> x) hlist26 , bench "Z" $ whnf (\(hOccursFst -> Z x) -> x) hlist26- ] , bgroup "sum" [ bench "A" $ whnf testExt (bury (A 0))@@ -107,7 +108,5 @@ , bench "T_" $ whnf testNaive (C19 (T 0)) , bench "Z_" $ whnf testNaive (C25 (Z 0)) ]- , bgroup "tuple" [- bench "A" $ whnf (\(a,b,c,d,e,f,g,h,i,j,k,l,M res,n,o,p,q,r,s,t,u,v,w,x,y,z) -> res) tuple26- ]+ ]
+ examples/test.hs view
@@ -0,0 +1,7 @@+import Data.Extensible++test = (42 :: Int) <% "hoge" <% False <% Nil++value = pluck test :: Int++main = print value
extensible.cabal view
@@ -1,5 +1,5 @@ name: extensible-version: 0.2.9+version: 0.2.10 synopsis: Extensible, efficient, lens-friendly data types homepage: https://github.com/fumieval/extensible bug-reports: http://github.com/fumieval/extensible/issues
src/Data/Extensible/Dictionary.hs view
@@ -83,7 +83,7 @@ instance WrapForall Show h xs => Show (h :| xs) where showsPrec d (UnionAt pos h) = showParen (d > 10) $ showString "embed "- . getShowsPrec (hlookup pos library) 11 h+ . views (sectorAt pos) getShowsPrec library 11 h instance WrapForall Eq h xs => Eq (h :| xs) where UnionAt p g == UnionAt q h = case compareMembership p q of
src/Data/Extensible/Inclusion.hs view
@@ -54,7 +54,7 @@ -- | /O(m log n)/ Select some elements. shrink :: (xs ⊆ ys) => h :* ys -> h :* xs-shrink h = hmap (\pos -> hlookup pos h) inclusion+shrink h = hmap (`hlookup` h) inclusion {-# INLINE shrink #-} -- | A lens for a subset (inefficient)@@ -66,7 +66,7 @@ -- | /O(log n)/ Embed to a larger union. spread :: (xs ⊆ ys) => h :| xs -> h :| ys-spread (UnionAt pos h) = UnionAt (hlookup pos inclusion) h+spread (UnionAt pos h) = views (sectorAt pos) UnionAt inclusion h {-# INLINE spread #-} -- | The inverse of 'inclusion'.@@ -83,5 +83,5 @@ -- | Narrow the range of the sum, if possible. retrench :: (Generate ys, xs ⊆ ys) => h :| ys -> Nullable ((:|) h) xs-retrench (UnionAt pos h) = flip UnionAt h `mapNullable` hlookup pos coinclusion+retrench (UnionAt pos h) = views (sectorAt pos) (mapNullable (`UnionAt`h)) coinclusion {-# INLINE retrench #-}
src/Data/Extensible/Internal.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}+{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances, FunctionalDependencies #-}+{-# LANGUAGE ScopedTypeVariables, BangPatterns, StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} ----------------------------------------------------------------------------- -- |@@ -16,6 +16,7 @@ -- A bunch of combinators that contains magic ------------------------------------------------------------------------ module Data.Extensible.Internal (Membership+ , getMemberId , runMembership , compareMembership , ord@@ -25,14 +26,20 @@ , navNext , navL , navR+ , (:*)(..) , Member(..) , (∈)() , Nat(..) , ToInt(..) , Lookup+ , ListIndex+ , LookupTree(..) , Succ , MapSucc+ , Pred+ , Div2 , Half+ , Head , Tail , lemmaHalfTail , lemmaMerging@@ -53,7 +60,7 @@ import Control.Monad import Unsafe.Coerce import Data.Typeable-import Language.Haskell.TH+import Language.Haskell.TH hiding (Pred) import Control.DeepSeq import Data.Bits import Data.Word@@ -70,8 +77,52 @@ $ conT ''Membership `appT` pure t `appT` varT (names !! n) -- | The position of @x@ in the type level set @xs@.-newtype Membership (xs :: [k]) (x :: k) = Membership Word deriving Typeable+newtype Membership (xs :: [k]) (x :: k) = Membership { getMemberId :: Word } deriving Typeable +-- | Lookup types+type family ListIndex (n :: Nat) (xs :: [k]) :: k where+ ListIndex Zero (x ': xs) = x+ ListIndex (SDNat n) (y ': xs) = ListIndex n (Half xs)+ ListIndex (DNat n) xs = ListIndex n (Half xs)++type family Pred (n :: Nat) :: Nat where+ Pred (SDNat Zero) = Zero+ Pred (SDNat n) = DNat n+ Pred (DNat n) = SDNat (Pred n)+ Pred Zero = Zero++type family Div2 (n :: Nat) :: Nat where+ Div2 (SDNat n) = n+ Div2 (DNat n) = n+ Div2 Zero = Zero++-- | The extensible product type+data (h :: k -> *) :* (s :: [k]) where+ Nil :: h :* '[]+ Tree :: !(h x)+ -> h :* Half xs+ -> h :* Half (Tail xs)+ -> h :* (x ': xs)++deriving instance Typeable (:*)++class LookupTree (n :: Nat) (xs :: [k]) x | n xs -> x where+ lookupTree :: Functor f => proxy n+ -> (h x -> f (h x))+ -> h :* xs -> f (h :* xs)++instance LookupTree Zero (x ': xs) x where+ lookupTree _ f (Tree h a b) = fmap (\h' -> Tree h' a b) (f h)+ {-# INLINE lookupTree #-}++instance LookupTree n (Half xs) x => LookupTree (SDNat n) (t ': xs) x where+ lookupTree _ f (Tree h a b) = fmap (\a' -> Tree h a' b) (lookupTree (Proxy :: Proxy n) f a)+ {-# INLINE lookupTree #-}++instance LookupTree (Pred n) (Half (Tail xs)) x => LookupTree (DNat n) (t ': xs) x where+ lookupTree _ f (Tree h a b) = fmap (\b' -> Tree h a b') (lookupTree (Proxy :: Proxy (Div2 (Pred (DNat n)))) (unsafeCoerce f) b)+ {-# INLINE lookupTree #-}+ instance NFData (Membership xs x) where rnf (Membership a) = rnf a @@ -137,8 +188,10 @@ -- | Unicode flipped alias for 'Member' type x ∈ xs = Member xs x --- | @Member x xs@ or @x ∈ xs@ indicates that @x@ is an element of @xs@.-class Member (xs :: [k]) (x :: k) where+type family Head (xs :: [k]) :: k where+ Head (x ': xs) = x++class (LookupTree (Head (Lookup x xs)) xs x) => Member xs x where membership :: Membership xs x -- | A type sugar to make type error more readable.@@ -156,10 +209,16 @@ Check x '[] = Missing x Check x xs = Ambiguous x -instance (Check x (Lookup x xs) ~ Expecting one, ToInt one) => Member xs x where+instance (Check x (Lookup x xs) ~ Expecting one, ToInt one, LookupTree (Head (Lookup x xs)) xs x) => Member xs x where membership = Membership (theInt (Proxy :: Proxy one)) {-# INLINE membership #-} +-- | Lookup types+type family Lookup (x :: k) (xs :: [k]) :: [Nat] where+ Lookup x (x ': xs) = Zero ': Lookup x xs+ Lookup x (y ': ys) = MapSucc (Lookup x ys)+ Lookup x '[] = '[]+ -- | Interleaved list type family Half (xs :: [k]) :: [k] where Half '[] = '[]@@ -189,12 +248,6 @@ instance ToInt n => ToInt (SDNat n) where theInt _ = (theInt (Proxy :: Proxy n) `unsafeShiftL` 1) + 1 {-# INLINE theInt #-}---- | Lookup types-type family Lookup (x :: k) (xs :: [k]) :: [Nat] where- Lookup x (x ': xs) = Zero ': Lookup x xs- Lookup x (y ': ys) = MapSucc (Lookup x ys)- Lookup x '[] = '[] -- | The successor of the number type family Succ (x :: Nat) :: Nat where
src/Data/Extensible/Internal/Rig.hs view
@@ -23,12 +23,12 @@ type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s -- | @'view' :: Lens' s a -> (a -> a) -> (s -> s)@-view :: ((a -> Const a a) -> (s -> Const a s)) -> s -> a+view :: ((a -> Const a a) -> s -> Const a s) -> s -> a view l = views l id {-# INLINE view #-} -- | @'views' :: Lens' s a -> (a -> r) -> (s -> r)@-views :: ((a -> Const r a) -> (s -> Const r s)) -> (a -> r) -> s -> r+views :: ((a -> Const r a) -> s -> Const r s) -> (a -> r) -> s -> r views = unsafeCoerce {-# INLINE views #-}
src/Data/Extensible/Product.hs view
@@ -45,20 +45,9 @@ import Data.Extensible.Internal.Rig import Data.Extensible.Internal.HList import Unsafe.Coerce-import Data.Typeable import Control.Applicative import Data.Monoid --- | The extensible product type-data (h :: k -> *) :* (s :: [k]) where- Nil :: h :* '[]- Tree :: !(h x)- -> h :* Half xs- -> h :* Half (Tail xs)- -> h :* (x ': xs)--deriving instance Typeable (:*)- -- | /O(1)/ Extract the head element. hhead :: h :* (x ': xs) -> h x hhead (Tree a _ _) = a@@ -140,8 +129,8 @@ {-# INLINE htabulate #-} -- | /O(log n)/ A lens for a specific element.-sector :: (x ∈ xs) => Lens' (h :* xs) (h x)-sector = sectorAt membership+sector :: forall h x xs. (x ∈ xs) => Lens' (h :* xs) (h x)+sector = lookupTree (Proxy :: Proxy (Head (Lookup x xs))) {-# INLINE sector #-} -- | /O(log n)/ A lens for a value in a known position.@@ -171,6 +160,7 @@ -- | Pure version of 'generateA'. generate :: Generate xs => (forall x. Membership xs x -> h x) -> h :* xs generate f = getK0 (generateA (K0 . f))+{-# INLINE generate #-} -- | Guarantees the all elements satisfies the predicate. class Forall c (xs :: [k]) where@@ -191,6 +181,7 @@ -- | Pure version of 'generateForA'. generateFor :: Forall c xs => proxy c -> (forall x. c x => Membership xs x -> h x) -> h :* xs generateFor p f = getK0 (generateForA p (K0 . f))+{-# INLINE generateFor #-} -- | Turn a product into 'HList'. toHList :: h :* xs -> HList h xs