packages feed

vinyl 0.3 → 0.4

raw patch · 23 files changed

+564/−426 lines, 23 filesdep +singletonsdep +template-haskelldep ~basedep ~vinyl

Dependencies added: singletons, template-haskell

Dependency ranges changed: base, vinyl

Files

Data/Vinyl.hs view
@@ -1,16 +1,16 @@ module Data.Vinyl-  ( module Data.Vinyl.Lens+  ( module Data.Vinyl.Core+  , module Data.Vinyl.Derived+  , module Data.Vinyl.Operators+  , module Data.Vinyl.Lens   , module Data.Vinyl.Witnesses-  , module Data.Vinyl.Field-  , module Data.Vinyl.Rec-  , module Data.Vinyl.Relation-  , module Data.Vinyl.Classes+  , module Data.Vinyl.Constraint   ) where -import           Data.Vinyl.Classes-import           Data.Vinyl.Field-import           Data.Vinyl.Lens-import           Data.Vinyl.Rec-import           Data.Vinyl.Relation-import           Data.Vinyl.Witnesses+import Data.Vinyl.Core+import Data.Vinyl.Derived+import Data.Vinyl.Operators+import Data.Vinyl.Lens+import Data.Vinyl.Constraint+import Data.Vinyl.Witnesses 
− Data/Vinyl/Classes.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE TypeOperators         #-}--module Data.Vinyl.Classes where--import Control.Applicative-import Data.Vinyl.Idiom.Identity---- | This class is a generalized, but non-pointed version of 'Applicative'. This--- is useful for types which range over functors rather than sets.-class Apply (arr :: k -> k -> k) (f :: k -> *) where-  (<<*>>) :: f (arr a b) -> f a -> f b---- | To accumulate effects distributed over a data type, you 'dist' it.-class Dist t where-  dist :: Applicative f => t f -> f (t Identity)---- | If a record is homogenous, you can fold over it.-class FoldRec r a where-  foldRec :: (a -> b -> b) -> b -> r -> b---- | '(~>)' is a morphism between functors.-newtype (f ~> g) x = NT { runNT :: f x -> g x }-
+ Data/Vinyl/Constraint.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}++module Data.Vinyl.Constraint+  ( (<:)(..)+  , (:~:)+  , (~=)+  , RecAll+  ) where++import Data.Vinyl.Core+import Data.Vinyl.Witnesses+import Data.Vinyl.TyFun+import GHC.Prim (Constraint)++-- | One record is a subtype of another if the fields of the latter are a+-- subset of the fields of the former.+class (xs :: [k]) <: (ys :: [k]) where+  cast :: Rec el f xs -> Rec el f ys++instance xs <: '[] where+  cast _ = RNil++instance (y ∈ xs, xs <: ys) => xs <: (y ': ys) where+  cast xs = ith (implicitly :: Elem y xs) xs :& cast xs+    where+      ith :: Elem r rs -> Rec el f rs -> f (el $ r)+      ith Here (a :& _) = a+      ith (There p) (_ :& as) = ith p as++-- | If two records types are subtypes of each other, that means that they+-- differ only in order of fields.+type r1 :~: r2 = (r1 <: r2, r2 <: r1)++-- | Term-level record congruence.+(~=) :: (Eq (Rec el f xs), xs :~: ys) => Rec el f xs -> Rec el f ys -> Bool+x ~= y = x == (cast y)++type family RecAll (el :: TyFun k l -> *) (f :: * -> *) (rs :: [k]) (c :: * -> Constraint) :: Constraint+type instance RecAll el f '[] c = ()+type instance RecAll el f (r ': rs) c = (c (f (el $ r)), RecAll el f rs c)+
+ Data/Vinyl/Core.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PolyKinds           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}++module Data.Vinyl.Core where++import Data.Vinyl.TyFun+import Control.Applicative+import Data.Monoid+import Data.Vinyl.Idiom.Identity+import Foreign.Ptr (castPtr, plusPtr)+import Foreign.Storable (Storable(..))++-- | A record is parameterized by a universe @u@, list of rows @rs@, a large+-- elimination @el@, and a type constructor @f@ to be applied to the+-- interpretation @el r@ of each of those @r@.+data Rec :: (TyFun u * -> *) -> (* -> *) -> [u] -> * where+  RNil :: Rec el f '[]+  (:&) :: !(f (el $ r)) -> !(Rec el f rs) -> Rec el f (r ': rs)+infixr :&++-- | Shorthand for a record with a single field. Lifts the field's+-- value into the chosen functor automatically.+(=:) :: Applicative f => sing k -> el $ k -> Rec el f '[ k ]+_ =: x = pure x :& RNil++-- | Shorthand for a record with a single field. This is useful for+-- @Applicative@ or @Monad@ic intialization of records as in the idiom:+--+-- > dist $ myField <-: someIO <+> yourField <-: otherIO+(<-:) :: sing r -> f (el $ r) -> Rec el f '[r]+_ <-: x = x :& RNil+infixr 6 <-:++-- | Records constructed using the above combinators will often be polymorphic+-- in their interpreter @el@. To avoid providing a type annotation, one can+-- provide their interpreters with a singleton tag and pass that in.+withUniverse :: (forall x. el x) -> Rec el f rs -> Rec el f rs+withUniverse _ x = x+{-# INLINE withUniverse #-}++instance Monoid (Rec el f '[]) where+  mempty = RNil+  RNil `mappend` RNil = RNil++instance (Monoid (el $ r), Monoid (Rec el f rs), Applicative f) => Monoid (Rec el f (r ': rs)) where+  mempty = pure mempty :& mempty+  (x :& xs) `mappend` (y :& ys) = liftA2 mappend x y :& (xs `mappend` ys)++instance Eq (Rec el f '[]) where+  _ == _ = True+instance (Eq (f (el $ r)), Eq (Rec el f rs)) => Eq (Rec el f (r ': rs)) where+  (x :& xs) == (y :& ys) = (x == y) && (xs == ys)++instance Storable (Rec el Identity '[]) where+  sizeOf _    = 0+  alignment _ = 0+  peek _      = return RNil+  poke _ RNil = return ()++instance (Storable (el $ r), Storable (Rec el Identity rs)) => Storable (Rec el Identity (r ': rs)) where+  sizeOf _ = sizeOf (undefined :: el $ r) + sizeOf (undefined :: Rec el Identity rs)+  {-# INLINABLE sizeOf #-}+  alignment _ =  alignment (undefined :: el $ r)+  {-# INLINABLE alignment #-}+  peek ptr = do !x <- peek (castPtr ptr)+                !xs <- peek (ptr `plusPtr` sizeOf (undefined :: el $ r))+                return $ Identity x :& xs+  {-# INLINABLE peek #-}+  poke ptr (Identity !x :& xs) = poke (castPtr ptr) x >>+                                 poke (ptr `plusPtr` sizeOf (undefined :: el $ r)) xs+  {-# INLINEABLE poke #-}+
− Data/Vinyl/Field.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE KindSignatures      #-}-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}--module Data.Vinyl.Field where--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707-import           Data.Proxy-#endif-import           GHC.TypeLits---- | A field contains a key and a type.-data (:::) :: Symbol -> * -> * where-  Field :: sy ::: t--#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707-instance KnownSymbol sy => Show (sy ::: t) where-  show Field = symbolVal (Proxy :: Proxy sy)-#else-instance SingI sy => Show (sy ::: t) where-  show Field = fromSing (sing :: Sing sy)-#endif
+ Data/Vinyl/Functor.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE FlexibleInstances #-}++module Data.Vinyl.Functor where++import Control.Applicative++class Presheaf f where+  contramap :: (a -> b) -> (f b -> f a)++newtype Lift op f g x = Lift { runLift :: op (f x) (g x) }++instance (Functor f, Functor g) => Functor (Lift (,) f g) where+  fmap f (Lift (x, y)) = Lift (fmap f x, fmap f y)++instance (Functor f, Functor g) => Functor (Lift Either f g) where+  fmap f (Lift (Left x)) = Lift . Left . fmap f $ x+  fmap f (Lift (Right x)) = Lift . Right . fmap f $ x++instance (Presheaf f, Presheaf g) => Presheaf (Lift (,) f g) where+  contramap f (Lift (x, y)) = Lift (contramap f x, contramap f y)++instance (Presheaf f, Presheaf g) => Presheaf (Lift Either f g) where+  contramap f (Lift (Left x)) = Lift . Left . contramap f $ x+  contramap f (Lift (Right x)) = Lift . Right . contramap f $ x++instance (Applicative f, Applicative g) => Applicative (Lift (,) f g) where+  pure x = Lift (pure x, pure x)+  Lift (f, g) <*> Lift (x, y) = Lift (f <*> x, g <*> y)++instance (Presheaf f, Functor g) => Functor (Lift (->) f g) where+  fmap f (Lift ηx) = Lift $ fmap f . ηx . contramap f++instance (Functor f, Presheaf g) => Presheaf (Lift (->) f g) where+  contramap f (Lift ηx) = Lift $ contramap f . ηx . fmap f+
− Data/Vinyl/Idiom/LazyIdentity.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}--module Data.Vinyl.Idiom.LazyIdentity where--import Control.Applicative-import Data.Foldable-import Data.Traversable--data LazyIdentity a-  = LazyIdentity-  { runLazyIdentity :: a-  } deriving (Functor, Foldable, Traversable)--instance Applicative LazyIdentity where-  pure = LazyIdentity-  (LazyIdentity f) <*> (LazyIdentity x) = LazyIdentity (f x)--instance Monad LazyIdentity where-  return = LazyIdentity-  (LazyIdentity x) >>= f = f x--instance Show a => Show (LazyIdentity a) where-  show (LazyIdentity x) = show x
+ Data/Vinyl/Idiom/Thunk.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}++module Data.Vinyl.Idiom.Thunk where++import Control.Applicative+import Data.Foldable+import Data.Traversable++data Thunk a+  = Thunk+  { runThunk :: a+  } deriving (Functor, Foldable, Traversable)++instance Applicative Thunk where+  pure = Thunk+  (Thunk f) <*> (Thunk x) = Thunk (f x)++instance Monad Thunk where+  return = Thunk+  (Thunk x) >>= f = f x++instance Show a => Show (Thunk a) where+  show (Thunk x) = show x
Data/Vinyl/Idiom/Validation.hs view
@@ -2,10 +2,11 @@  module Data.Vinyl.Idiom.Validation where +import Data.Vinyl.Idiom.Identity+import Data.Vinyl.Functor+ import Control.Applicative import Data.Monoid-import Data.Vinyl.Classes-import Data.Vinyl.Idiom.Identity  -- | A type which is similar to 'Either', except that it has a -- slightly different Applicative instance.@@ -15,17 +16,17 @@   deriving (Show, Eq)  -- | Validators transform identities into results.-type Validator e = Identity ~> Result e+type Validator e = Lift (->) Identity (Result e)  instance Functor (Result e) where   fmap f (Success x) = Success $ f x-  fmap f (Failure e) = Failure e+  fmap _ (Failure e) = Failure e  -- | The 'Applicative' instance to 'Result' relies on its error type -- being a 'Monoid'. That way, it can accumulate errors. instance Monoid e => Applicative (Result e) where   pure = Success   (Success f) <*> (Success x)  = Success $ f x-  (Failure e) <*> (Success x)  = Failure e-  (Success f) <*> (Failure e)  = Failure e+  (Failure e) <*> (Success _)  = Failure e+  (Success _) <*> (Failure e)  = Failure e   (Failure e) <*> (Failure e') = Failure $ e <> e'
Data/Vinyl/Lens.hs view
@@ -1,40 +1,44 @@ {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE GADTs                 #-}+{-# LANGUAGE PolyKinds             #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE TypeOperators         #-}+ -- | A small, /en passant/ lens implementation to provide accessors -- for record fields. Lenses produced with 'rLens' are fully -- compatible with the @lens@ package. module Data.Vinyl.Lens where-import Control.Applicative-import Data.Vinyl.Idiom.Identity-import Data.Vinyl.Field-import Data.Vinyl.Rec++import Data.Vinyl.Core+import Data.Vinyl.Derived+import Data.Vinyl.TyFun import Data.Vinyl.Witnesses+import Data.Vinyl.Idiom.Identity +import Control.Applicative+ -- | Project a field from a 'Rec'.-rGet' :: IElem (sy ::: t) rs => (sy ::: t) -> Rec rs f -> f t+rGet' :: (r ∈ rs) => sing r -> Rec el f rs -> f (el $ r) rGet' r = getConst . rLens' r Const {-# INLINE rGet' #-}  -- | Project a field from a 'PlainRec'.-rGet :: IElem (sy ::: t) rs => (sy ::: t) -> PlainRec rs -> t+rGet :: (r ∈ rs) => sing r -> PlainRec el rs -> el $ r rGet = (runIdentity .) . rGet' {-# INLINE rGet #-}  -- | Set a field in a 'Rec' over an arbitrary functor.-rPut' :: IElem (sy ::: t) rs => (sy ::: t) -> f t -> Rec rs f -> Rec rs f+rPut' :: (r ∈ rs) => sing r -> f (el $ r) -> Rec el f rs -> Rec el f rs rPut' r x = runIdentity . rLens' r (Identity . const x) {-# INLINE rPut' #-}  -- | Set a field in a 'PlainRec'.-rPut :: IElem (sy:::t) rs => (sy:::t) -> t -> PlainRec rs -> PlainRec rs+rPut :: (r ∈ rs) => sing r -> el $ r -> PlainRec el rs -> PlainRec el rs rPut r x = rPut' r (Identity x) {-# INLINE rPut #-}  -- | Modify a field.-rMod :: (IElem (sy:::t) rs, Functor f)-     => (sy:::t) -> (t -> t) -> Rec rs f -> Rec rs f+rMod :: (r ∈ rs , Functor f) => sing r -> (el $ r -> el $ r) -> Rec el f rs -> Rec el f rs rMod r f = runIdentity . rLens' r (Identity . fmap f) {-# INLINE rMod #-} @@ -45,11 +49,10 @@ -- does not support polymorphic update. In the parlance of the @lens@ -- package, ----- > rLens' :: IElem (sy:::t) rs => (sy:::t) -> Lens' (Rec rs f) (f t)-rLens' :: forall r rs sy t f g. (r ~ (sy:::t), IElem r rs, Functor g)-       => r -> (f t -> g (f t)) -> Rec rs f -> g (Rec rs f)+-- > rLens' :: (r ∈ rs) => Sing r -> Lens' (Rec el f rs) (f (el $ r))+rLens' :: forall r rs f g el sing. (r ∈ rs , Functor g) => sing r -> (f (el $ r) -> g (f (el $ r))) -> Rec el f rs -> g (Rec el f rs) rLens' _ f = go implicitly-  where go :: Elem r rr -> Rec rr f -> g (Rec rr f)+  where go :: Elem r rr -> Rec el f rr -> g (Rec el f rr)         go Here (x :& xs) = fmap (:& xs) (f x)         go (There Here) (a :& x :& xs) = fmap ((a :&) . (:& xs)) (f x)         go (There (There Here)) (a :& b :& x :& xs) =@@ -62,7 +65,7 @@           fmap (\xs' -> a :& b :& c :& d :& xs') (go' p xs)         {-# INLINE go #-} -        go' :: Elem r rr -> Rec rr f -> g (Rec rr f)+        go' :: Elem r rr -> Rec el f rr -> g (Rec el f rr)         go' Here (x :& xs) = fmap (:& xs) (f x)         go' (There p) (x :& xs) = fmap (x :&) (go p xs)         {-# INLINABLE go' #-}@@ -72,9 +75,8 @@ -- from the @lens@ package. Note that polymorphic update is not -- supported. In the parlance of the @lens@ package, ----- > rLens :: IElem (sy:::t) rs => (sy:::t) -> Lens' (PlainRec rs) t-rLens :: forall r rs sy t g. (r ~ (sy:::t), IElem r rs, Functor g)-      => r -> (t -> g t) -> PlainRec rs -> g (PlainRec rs)+-- > rLens :: (r ∈ rs) => sing r -> Lens' (PlainRec el rs) (el $ r)+rLens :: forall r rs g el sing. (r ∈ rs , Functor g) => sing r -> (el $ r -> g (el $ r)) -> PlainRec el rs -> g (PlainRec el rs) rLens r = rLens' r . lenser runIdentity (const Identity)   where lenser sa sbt afb s = sbt s <$> afb (sa s) {-# INLINE rLens #-}
+ Data/Vinyl/Operators.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PolyKinds             #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}++module Data.Vinyl.Operators+  ( (<<$>>)+  , (<<*>>)+  , (<+>)+  , rpure+  , rtraverse+  , rdist+  , rdistLazy+  , foldRec+  , recToList+  , showWithNames+  , rshow+  ) where++import Data.Vinyl.Core+import Data.Vinyl.Functor+import Data.Vinyl.TyFun+import Data.Vinyl.Witnesses+import Data.Vinyl.Constraint+import Data.Vinyl.Derived+import qualified Data.Vinyl.Idiom.Identity as I+import qualified Data.Vinyl.Idiom.Thunk as I+import qualified Data.Vinyl.Universe.Const as U++import Control.Applicative+import qualified Data.List as L (intercalate)++-- | Append for records.+(<+>) :: Rec el f as -> Rec el f bs -> Rec el f (as ++ bs)+RNil      <+> xs = xs+(x :& xs) <+> ys =  x :& (xs <+> ys)+infixr 5  <+>++-- | Append for type-level lists.+type family (as :: [k]) ++ (bs :: [k]) :: [k]+type instance '[] ++ bs = bs+type instance (a ': as) ++ bs  = a ': (as ++ bs)++(<<$>>) :: (forall x. f x -> g x) -> Rec el f rs -> Rec el g rs+_   <<$>> RNil    = RNil+eta <<$>> x :& xs = eta x :& (eta <<$>> xs)+infixl 8 <<$>>+{-# INLINE (<<$>>) #-}++(<<*>>) :: Rec el (Lift (->) f g) rs -> Rec el f rs -> Rec el g rs+RNil    <<*>> RNil    = RNil+f :& fs <<*>> x :& xs = runLift f x :& (fs <<*>> xs)+infixl 8 <<*>>+{-# INLINE (<<*>>) #-}++class RecApplicative rs where+  rpure :: (forall x. f x) -> Rec el f rs+instance RecApplicative '[] where+  rpure _ = RNil+instance RecApplicative rs => RecApplicative (f ': rs) where+  rpure s = s :& rpure s++class FoldRec r a where+  foldRec :: (a -> b -> b) -> b -> r -> b+instance FoldRec (Rec el f '[]) a where+  foldRec _ z RNil = z+instance (t ~ (el $ r), FoldRec (Rec el f rs) (f t)) => FoldRec (Rec el f (r ': rs)) (f t) where+  foldRec f z (x :& xs) = f x (foldRec f z xs)++-- | Accumulates a homogenous record into a list+recToList :: FoldRec (Rec el f rs) (f t) => Rec el f rs -> [f t]+recToList = foldRec (\e a -> [e] ++ a) []++rtraverse :: Applicative h => (forall x. f x -> h (g x)) -> Rec el f rs -> h (Rec el g rs)+rtraverse _ RNil      = pure RNil+rtraverse f (x :& xs) = (:&) <$> f x <*> rtraverse f xs++rdist :: Applicative f => Rec el f rs -> f (PlainRec el rs)+rdist = rtraverse $ fmap I.Identity++rdistLazy :: Applicative f => Rec el f rs -> f (LazyPlainRec el rs)+rdistLazy = rtraverse $ fmap I.Thunk++showWithNames :: RecAll el f rs Show => PlainRec (U.Const String) rs -> Rec el f rs -> String+showWithNames names rec = "{ " ++ L.intercalate ", " (go names rec []) ++ " }"+  where+    go :: RecAll el f rs Show => PlainRec (U.Const String) rs -> Rec el f rs -> [String] -> [String]+    go RNil RNil ss = ss+    go (I.Identity n :& ns) (x :& xs) ss = (n ++ " =: " ++ show x) : go ns xs ss++rshow :: (Implicit (PlainRec (U.Const String) rs), RecAll el f rs Show) => Rec el f rs -> String+rshow = showWithNames implicitly+
− Data/Vinyl/Rec.hs
@@ -1,146 +0,0 @@-{-# LANGUAGE BangPatterns              #-}-{-# LANGUAGE CPP                       #-}-{-# LANGUAGE ConstraintKinds           #-}-{-# LANGUAGE DataKinds                 #-}-{-# LANGUAGE FlexibleContexts          #-}-{-# LANGUAGE FlexibleInstances         #-}-{-# LANGUAGE GADTs                     #-}-{-# LANGUAGE InstanceSigs              #-}-{-# LANGUAGE KindSignatures            #-}-{-# LANGUAGE MultiParamTypeClasses     #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE PolyKinds                 #-}-{-# LANGUAGE RankNTypes                #-}-{-# LANGUAGE ScopedTypeVariables       #-}-{-# LANGUAGE TypeFamilies              #-}-{-# LANGUAGE TypeOperators             #-}--module Data.Vinyl.Rec-  ( Rec(..)-  , PlainRec-  , LazyPlainRec-  , (=:)-  , (<+>)-  , (<-:)-  , type (++)-  , fixRecord-  ) where--import Data.Vinyl.Classes-import Control.Applicative-import Data.Vinyl.Idiom.Identity-import Data.Vinyl.Idiom.LazyIdentity-import Data.Vinyl.Field-import Foreign.Ptr (castPtr, plusPtr)-import Foreign.Storable (Storable(..))-import GHC.TypeLits-import Data.Monoid---- | A record is parameterized by a list of fields and a functor--- to be applied to each of those fields.-data Rec :: [*] -> (* -> *) -> * where-  RNil :: Rec '[] f-  (:&) :: !(f t) -> !(Rec rs f) -> Rec ((sy ::: t) ': rs) f-infixr :&---- | Fixes a polymorphic record into the 'Identity' functor.-fixRecord :: (forall f. Applicative f => Rec rs f) -> PlainRec rs-fixRecord xs = xs--fixRecordLazy :: (forall f. Applicative f => Rec rs f) -> LazyPlainRec rs-fixRecordLazy xs = xs---- | Fields of plain records are in the 'Identity' functor.-type PlainRec rs = Rec rs Identity-type LazyPlainRec rs = Rec rs LazyIdentity---- | Append for records.-(<+>) :: Rec as f -> Rec bs f -> Rec (as ++ bs) f-RNil      <+> xs = xs-(x :& xs) <+> ys =  x :& (xs <+> ys)-infixr 5  <+>---- | Shorthand for a record with a single field. Lifts the field's--- value into the chosen functor automatically.-(=:) :: Applicative f => sy ::: t -> t -> Rec '[sy ::: t] f-_ =: b = pure b :& RNil---- | Shorthand for a record with a single field of an 'Applicative'--- type. This is useful for @Applicative@ or @Monad@ic intialization--- of records as in the idiom:------ > dist $ myField <-: someIO <+> yourField <-: otherIO-(<-:) :: Applicative f => sy ::: t -> f t -> Rec '[sy ::: t] f-_ <-: b = b :& RNil-infixr 6 <-:---- | Append for type-level lists.-type family (as :: [*]) ++ (bs :: [*]) :: [*]-type instance '[] ++ bs = bs-type instance (a ': as) ++ bs  = a ': (as ++ bs)---instance Show (Rec '[] f) where-  show RNil = "{}"-instance (-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 707-    KnownSymbol sy,-#else-    SingI sy,-#endif-    Show (g t), Show (Rec fs g)) => Show (Rec ((sy ::: t) ': fs) g) where-  show (x :& xs) = show (Field :: sy ::: t) ++ " :=: " ++ show x ++ ", " ++ show xs---instance Eq (Rec '[] f) where-  _ == _ = True-instance (Eq (g t), Eq (Rec fs g)) => Eq (Rec ((s ::: t) ': fs) g) where-  (x :& xs) == (y :& ys) = (x == y) && (xs == ys)---instance Monoid (Rec '[] f) where-  mempty = RNil-  RNil `mappend` RNil = RNil-instance (Monoid t, Monoid (Rec fs g), Applicative g) => Monoid (Rec ((s ::: t) ': fs) g) where-  mempty = pure mempty :& mempty-  (x :& xs) `mappend` (y :& ys) = liftA2 mappend x y :& (xs `mappend` ys)----- | Records can be applied to each other.-instance Apply (~>) (Rec rs) where-  RNil <<*>> RNil = RNil-  (f :& fs) <<*>> (x :& xs) = runNT f x :& (fs <<*>> xs)---- | Records may be distributed to accumulate the effects of their fields.-instance Dist (Rec rs) where-  dist RNil      = pure RNil-  dist (x :& xs) = (:&) <$> (pure <$> x) <*> dist xs--instance FoldRec (Rec '[] f) a where-  foldRec _ z RNil = z--instance FoldRec (Rec fs g) (g t) => FoldRec (Rec ((s ::: t) ': fs) g) (g t) where-  foldRec f z (x :& xs) = f x (foldRec f z xs)---- | Accumulates a homogenous record into a list-recToList :: FoldRec (Rec fs g) (g t) => Rec fs g -> [g t]-recToList = foldRec (\e a -> [e] ++ a) []--instance Storable (PlainRec '[]) where-  sizeOf _    = 0-  alignment _ = 0-  peek _      = return RNil-  poke _ RNil = return ()--instance (Storable t, Storable (PlainRec rs)) => Storable (PlainRec ((sy:::t) ': rs)) where-  sizeOf _ = sizeOf (undefined :: t) + sizeOf (undefined :: PlainRec rs)-  {-# INLINABLE sizeOf #-}-  alignment _ =  alignment (undefined :: t)-  {-# INLINABLE alignment #-}-  peek ptr = do !x <- peek (castPtr ptr)-                !xs <- peek (ptr `plusPtr` sizeOf (undefined :: t))-                return $ Identity x :& xs-  {-# INLINABLE peek #-}-  poke ptr (Identity !x :& xs) = poke (castPtr ptr) x >>-                                 poke (ptr `plusPtr` sizeOf (undefined :: t)) xs-  {-# INLINEABLE poke #-}
− Data/Vinyl/Relation.hs
@@ -1,57 +0,0 @@-{-# LANGUAGE ConstraintKinds       #-}-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE UndecidableInstances  #-}--module Data.Vinyl.Relation-  ( (<:)(..)-  , (:~:)-  , (~=)-  -- , rIso-  ) where--import           Data.Vinyl.Field-import           Data.Vinyl.Lens-import           Data.Vinyl.Rec-import           Data.Vinyl.Witnesses--import           GHC.Prim             (Constraint)---- | A subtyping relation.-class (IsSubtype r1 r2) => r1 <: r2 where-  cast :: r1 -> r2---- | One record is a subtype of another if the fields of the latter are a--- subset of the fields of the former.-type family IsSubtype r1 r2 :: Constraint-type instance IsSubtype (Rec ss f) (Rec ts f) = ISubset ts ss---- | If two records types are subtypes of each other, that means that they--- differ only in order of fields.-type r1 :~: r2 = (r1 <: r2, r2 <: r1)---- | Term-level record congruence.-(~=) :: (Eq a, a :~: b) => a -> b -> Bool-x ~= y = x == (cast y)--instance Rec xs f <: Rec '[] f where-  cast _ = RNil--instance (y ~ (sy ::: t), IElem y xs, Rec xs f <: Rec ys f) => Rec xs f <: Rec (y ': ys) f where-  cast r = rGet' field r :& cast r-    where field = lookupField (implicitly :: Elem y xs) r--lookupField :: Elem x xs -> Rec xs f -> x-lookupField Here      (_ :& _)  = Field-lookupField (There p) (_ :& xs) = lookupField p xs---- rIso :: (r1 :~: r2) => Iso' r1 r2--- rIso = iso cast cast-
+ Data/Vinyl/TH.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}++module Data.Vinyl.TH+  ( makeUniverse+  , makeUniverse'+  , Semantics(..)+  , semantics+  ) where++import Language.Haskell.TH+import Data.Vinyl.TyFun++makeUniverse :: Name -> Q [Dec]+makeUniverse u = makeUniverse' u ("El" ++ nameBase u)++makeUniverse' :: Name -> String -> Q [Dec]+makeUniverse' u elName = do+  let elu = mkName elName+  u' <- conT u++  tvs <- do+    el <- newName "el"+    tyfun <- conT ''TyFun+    return [KindedTV el (AppT (AppT tyfun u') StarT)]++  let cons = [NormalC elu []]+  return [DataD [] elu tvs cons []]++class TyRep r where+  asType :: r -> TypeQ+instance TyRep Name where+  asType = conT+instance TyRep (Q Type) where+  asType = id++data Semantics = forall s t. (TyRep t, TyRep s) => t :~> s++semantics :: Name -> [Semantics] -> Q [Dec]+semantics elu sems = sequence (map inst sems)+  where+    inst :: Semantics -> Q Dec+    inst (u :~> t) = do+      elu' <- conT elu+      u' <- asType u+      t' <- asType t+      return $ TySynInstD ''App (TySynEqn [elu',u'] t')
+ Data/Vinyl/TyFun.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}++module Data.Vinyl.TyFun where++data TyFun :: * -> * -> *+type family App (f :: TyFun k l -> *) (a :: k) :: l++data TC :: (k -> *) -> TyFun k * -> *+type instance App (TC t) x = t x+type f $ x = App f x+
− Data/Vinyl/Unicode.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE ConstraintKinds           #-}-{-# LANGUAGE NoMonomorphismRestriction #-}-{-# LANGUAGE TypeOperators             #-}-{-# LANGUAGE UnicodeSyntax             #-}--module Data.Vinyl.Unicode where--import           Data.Vinyl.Rec-import           Data.Vinyl.Relation-import           Data.Vinyl.Witnesses--type x ∈ xs = IElem x xs-type xs ⊆ ys = ISubset xs ys-type r1 ≅ r2 = r1 :~: r2--(≅) = (~=)
+ Data/Vinyl/Universe.hs view
@@ -0,0 +1,7 @@+module Data.Vinyl.Universe+  ( module Data.Vinyl.Universe.Id+  , module Data.Vinyl.Universe.Field+  ) where++import Data.Vinyl.Universe.Id+import Data.Vinyl.Universe.Field
+ Data/Vinyl/Universe/Const.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE DataKinds    #-}+{-# LANGUAGE GADTs        #-}+{-# LANGUAGE PolyKinds    #-}+{-# LANGUAGE TypeFamilies #-}++module Data.Vinyl.Universe.Const (Const(..)) where++import Data.Vinyl.TyFun++data Const :: * -> (TyFun k *) -> * where+  Const :: Const t el++type instance App (Const t) x = t
+ Data/Vinyl/Universe/Field.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE DataKinds     #-}+{-# LANGUAGE GADTs         #-}+{-# LANGUAGE PolyKinds     #-}+{-# LANGUAGE TypeFamilies  #-}+{-# LANGUAGE TypeOperators #-}++module Data.Vinyl.Universe.Field where++import Data.Vinyl.TyFun+import GHC.TypeLits++data (sy :: k) ::: (t :: *)++data SField :: * -> * where+  SField :: KnownSymbol sy => SField (sy ::: t)++data ElField :: (TyFun * *) -> * where+  ElField :: ElField el+type instance App ElField (sy ::: t) = t
+ Data/Vinyl/Universe/Id.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE DataKinds    #-}+{-# LANGUAGE GADTs        #-}+{-# LANGUAGE PolyKinds    #-}+{-# LANGUAGE TypeFamilies #-}++module Data.Vinyl.Universe.Id (Id(..)) where++import Data.Vinyl.TyFun++data Id :: (TyFun k k) -> * where+  Id :: Id el+type instance App Id x = x+
Data/Vinyl/Witnesses.hs view
@@ -20,24 +20,10 @@  -- | A constraint for implicit resolution of list membership proofs. type IElem x xs = Implicit (Elem x xs)---- | An inductive list subset relation.-data Subset :: [k] -> [k] -> * where-  SubsetNil  :: Subset '[] xs-  SubsetCons :: Elem x ys-             -> Subset xs ys-             -> Subset (x ': xs) ys---- | A constraint for implicit resolution of list subset proofs.-type ISubset xs ys = Implicit (Subset xs ys)+type x ∈ xs = IElem x xs  instance Implicit (Elem x (x ': xs)) where   implicitly = Here instance Implicit (Elem x xs) => Implicit (Elem x (y ': xs)) where   implicitly = There implicitly--instance Implicit (Subset '[] xs) where-  implicitly = SubsetNil-instance (IElem x ys, ISubset xs ys) => Implicit (Subset (x ': xs) ys) where-  implicitly = SubsetCons implicitly implicitly 
tests/Intro.lhs view
@@ -17,45 +17,72 @@ Let’s work through a quick example. We’ll need to enable some language extensions first: -> {-# LANGUAGE DataKinds, TypeOperators #-}-> {-# LANGUAGE FlexibleContexts, NoMonomorphismRestriction #-}-> {-# LANGUAGE GADTs #-}+> {-# LANGUAGE DataKinds, PolyKinds, TypeOperators, TypeFamilies #-}+> {-# LANGUAGE FlexibleContexts, FlexibleInstances, NoMonomorphismRestriction #-}+> {-# LANGUAGE GADTs, TemplateHaskell, TypeSynonymInstances #-} > import Data.Vinyl-> import Data.Vinyl.Unicode+> import Data.Vinyl.TyFun+> import Data.Vinyl.TH+> import Data.Vinyl.Functor > import Data.Vinyl.Idiom.Identity > import Data.Vinyl.Idiom.Validation+> import Data.Vinyl.Witnesses+> import qualified Data.Vinyl.Universe.Const as U > import Control.Applicative > import Control.Lens hiding (Identity) > import Data.Char > import Test.DocTest+> import Data.Singletons.TH -Let’s define the fields we want to use:+Let’s define a universe of fields which we want to use: -> name     = Field :: "name"     ::: String-> age      = Field :: "age"      ::: Int-> sleeping = Field :: "sleeping" ::: Bool+> data Fields = Name | Age | Sleeping | Master deriving Show+> genSingletons [ ''Fields ]+> makeUniverse' ''Fields "ElF"+> semantics ''ElF [ 'Name     :~> ''String+>                 , 'Age      :~> ''Int+>                 , 'Sleeping :~> ''Bool+>                 ]  Now, let’s try to make an entity that represents a man: -> jon = name =: "jon"->    <+> age =: 20->    <+> sleeping =: False+> jon = SName =: "jon"+>    <+> SAge =: 20+>    <+> SSleeping =: False + We could make an alias for the sort of entity that jon is: -> type LifeForm = ["name" ::: String, "age" ::: Int, "sleeping" ::: Bool]-> jon :: PlainRec LifeForm+> type LifeForm = [Name, Age, Sleeping]+> jon :: PlainRec ElF LifeForm +We can print out the record by assigning names to each field:++> instance Implicit (PlainRec (U.Const String) [ Name, Age, Sleeping ]) where+>   implicitly = SName     =: "name"+>            <+> SAge      =: "age"+>            <+> SSleeping =: "sleeping"++> -- | >>> rshow jon+> -- "{ name =: \"jon\", age =: 20, sleeping =: False }"+ The types are inferred, though, so this is unnecessary unless you’d like to reuse the type later. Now, make a dog! Dogs are life-forms, but unlike men, they have masters. So, let’s build my dog: -> master = Field :: "master" ::: PlainRec LifeForm-> tucker = name =: "tucker"->       <+> age =: 7->       <+> sleeping =: True->       <+> master =: jon+> semantics ''ElF [ 'Master :~> [t| PlainRec ElF LifeForm |] ] +> tucker = withUniverse ElF $+>   SName =: "tucker"+>   <+> SAge =: 7+>   <+> SSleeping =: True+>   <+> SMaster =: jon++It was necessary to specify the interpreter for the universe in which `tucker`+lives, since (lacking a type annotation), records constructed using `(<+>)` and+`(=:)` are polymorphic with respect to `el`. We can help along the type+inference by giving it explicitly using `withUniverse`.+ Using Lenses ------------ @@ -65,8 +92,8 @@ on a particular field in the record for access and update, without losing additional information: -> wakeUp :: (("sleeping" ::: Bool) ∈ fields) => PlainRec fields -> PlainRec fields-> wakeUp = sleeping `rPut` False+> wakeUp :: (Sleeping ∈ fields) => PlainRec ElF fields -> PlainRec ElF fields+> wakeUp = SSleeping `rPut` False  Now, the type annotation on wakeUp was not necessary; I just wanted to show how intuitive the type is. Basically, it takes as an input any@@ -77,34 +104,30 @@ > jon' = wakeUp jon  > -- |-> -- >>> tucker' ^. rLens sleeping+> -- >>> tucker' ^. rLens SSleeping > -- False > ---> -- >>> tucker ^. rLens sleeping+> -- >>> tucker ^. rLens SSleeping > -- True > ---> -- >>> jon' ^. rLens sleeping+> -- >>> jon' ^. rLens SSleeping > -- False  We can also access the entire lens for a field using the rLens function; since lenses are composable, it’s super easy to do deep update on a record: -> masterSleeping :: (("master" ::: PlainRec LifeForm) ∈ fields) => Lens' (PlainRec fields) Bool-> masterSleeping = rLens master . rLens sleeping+> masterSleeping :: (Master ∈ fields) => Lens' (PlainRec ElF fields) Bool+> masterSleeping = rLens SMaster . rLens SSleeping > tucker'' = masterSleeping .~ True $ tucker' -> -- | >>> tucker'' ^. rLens master . rLens sleeping++> -- | >>> tucker'' ^. masterSleeping > -- True -Again, the type annotation is unnecessary. In fact, the seperate-definition is also unnecessary, and we could just define:+Again, the type annotation is unnecessary. -> tucker''' = rLens master . rLens sleeping .~ True $ tucker' -> -- | >>> tucker''' ^. rLens master . rLens sleeping-> -- True- Subtyping Relation and Coercion ------------------------------- @@ -117,15 +140,15 @@  Therefore, the following works: -> upcastedTucker :: PlainRec LifeForm-> upcastedTucker = cast (fixRecord tucker)+> upcastedTucker :: PlainRec ElF LifeForm+> upcastedTucker = cast (toPlainRec tucker) -The reason for using `fixRecord` will become clear a bit later.+The reason for using `toPlainRec` will become clear a bit later.  The subtyping relationship between record types is expressed with the `(<:)` constraint; so, cast is of the following type: -< cast :: r1 <: r2 => r1 -> r2+< cast :: r1 <: r2 => Rec r1 f -> Rec r2 f  Also provided is a `(≅)` constraint which indicates record congruence (that is, two record types differ only in the order of their fields).@@ -133,13 +156,13 @@ Records are polymorphic over functors ------------------------------------- -So far, we’ve been working with the PlainRec type; but below that,-there is something a bit more advanced called Rec, which looks like+So far, we’ve been working with the `PlainRec` type; but below that,+there is something a bit more advanced called `Rec`, which looks like this: -< data Rec :: [*] -> (* -> *) -> * where-<   RNil :: Rec '[] f-<   (:&) :: (r ~ (sy ::: t)) => f t -> Rec rs f -> Rec (r ': rs) f+< data Rec :: (TyFun u * -> *) -> (* -> *) -> [u] -> * where+<   RNil :: Rec el f '[]+<   (:&) :: f (el $ r) -> Rec el f rs -> Rec el f (r ': rs)  The second parameter is a functor, in which every element of the record will be placed. In `PlainRec`, the functor is just set to@@ -148,22 +171,23 @@ Let’s imagine that we want to do validation on a record that represents a name and an age: -> type Person = ["name" ::: String, "age" ::: Int]+> type Person = [Name, Age]  We’ve decided that names must be alphabetic, and ages must be positive. For validation, we’ll use a type that’s included here called `Result e a`, which is similar to `Either`, except that its `Applicative` instance accumulates monoidal errors on the left. -> goodPerson :: PlainRec Person-> goodPerson = name =: "Jon"->          <+> age =: 20-> badPerson = name =: "J#@#$on"->          <+> age =: 20-> validatePerson :: PlainRec Person -> Result [String] (PlainRec Person)-> validatePerson p = (\n a -> name =: n <+> age =: a) <$> vName <*> vAge where->   vName = validateName (rGet name p)->   vAge  = validateAge  (rGet age p)+> goodPerson :: PlainRec ElF Person+> goodPerson = SName =: "Jon"+>          <+> SAge  =: 20+> badPerson = SName =: "J#@#$on"+>         <+> SAge  =: 20++> validatePerson :: PlainRec ElF Person -> Result [String] (PlainRec ElF Person)+> validatePerson p = (\n a -> SName =: n <+> SAge =: a) <$> vName <*> vAge where+>   vName = validateName (rGet SName p)+>   vAge  = validateAge  (rGet SAge p) > >   validateName str | all isAlpha str = Success str >   validateName _ = Failure [ "name must be alphabetic" ]@@ -191,22 +215,22 @@ then that record could be applied to a plain one, to get a record of validated fields? That’s what we’re going to do. -Vinyl provides a type of validators, which is basically a natural-transformation from the `Identity` functor to the `Result` functor, which-we just used above.+Vinyl provides a type of validators, which is the class of functions from the+`Identity` functor to the `Result` functor at some type. -< type Validator e = Identity ~> Result e+< type Validator e = Lift (->) Identity ~> Result e  Let’s parameterize a record by it: when we do, then an element of type `a` should be a function `Identity a -> Result e a`: -> vperson :: Rec Person (Validator [String])-> vperson = NT validateName :& NT validateAge :& RNil where+> vperson :: Rec ElF (Validator [String]) Person+> vperson = Lift validateName :& Lift validateAge :& RNil where >    validateName (Identity str) | all isAlpha str = Success str >    validateName _ = Failure [ "name must be alphabetic" ] >    validateAge (Identity i) | i >= 0 = Success i >    validateAge _ = Failure [ "age must be positive" ] + And we can use the special application operator `<<*>>` (which is analogous to `<*>`, but generalized a bit) to use this to validate a record:@@ -214,29 +238,29 @@ > goodPersonResult = vperson <<*>> goodPerson > badPersonResult  = vperson <<*>> badPerson -goodPersonResult === name :=: Success "Jon", age :=: Success 20, {}-badPersonResult  === name :=: Failure ["name must be alphabetic"], age :=: Success 20, {}+< goodPersonResult === SName :=: Success "Jon", SAge :=: Success 20, {}+< badPersonResult  === SName :=: Failure ["name must be alphabetic"], SAge :=: Success 20, {}  > -- |-> -- >>> isSuccess $ goodPersonResult ^. rLens' name+> -- >>> isSuccess $ goodPersonResult ^. rLens' SName > -- True-> -- >>> isSuccess $ goodPersonResult ^. rLens' age+> -- >>> isSuccess $ goodPersonResult ^. rLens' SAge > -- True-> -- >>> isSuccess $ badPersonResult ^. rLens' name+> -- >>> isSuccess $ badPersonResult ^. rLens' SName > -- False-> -- >>> isSuccess $ badPersonResult ^. rLens' age+> -- >>> isSuccess $ badPersonResult ^. rLens' SAge > -- True  So now we have a partial record, and we can still do stuff with its contents. Next, we can even recover the original behavior of the validator (that is, to give us a value of type `Result [String]-(PlainRec Person)`) using `dist`:+(PlainRec Person)`) using `rdist`: -> distGoodPerson = dist goodPersonResult-> distBadPerson  = dist badPersonResult+> distGoodPerson = rdist goodPersonResult+> distBadPerson  = rdist badPersonResult -`distGoodPerson === Success name :=: "Jon", age :=: 20, {}`-`distBadPerson  === Failure ["name must be alphabetic"]``+< distGoodPerson === Success name :=: "Jon", age :=: 20, {}+< distBadPerson  === Failure ["name must be alphabetic"]  > -- | > -- >>> isSuccess distGoodPerson@@ -250,15 +274,15 @@ If you produced a record using `(=:)` and `(<+>)` without providing a type annotation, then its type is something like this: -< record :: Applicative f => Record [ <bunch of stuff> ] f+< record :: Applicative f => Rec el f [ <bunch of stuff> ]  The problem is then we can’t do anything with the record that requires us to know what its functor is. For instance, `cast` will fail. So, we might try to provide a type annotation, but that can be a bit brittle-and frustrating to have to do. To alleviate this problem, `fixRecord` is+and frustrating to have to do. To alleviate this problem, `toPlainRec` is provided: -< fixRecord :: (forall f. Applicative f => Rec rs f) -> PlainRec rs+< toPlainRec :: (forall f. Applicative f => Rec el f rs) -> PlainRec el rs  --- @@ -266,3 +290,4 @@  > main :: IO () > main = doctest ["tests/Intro.lhs"]+
vinyl.cabal view
@@ -1,5 +1,5 @@ name:                vinyl-version:             0.3+version:             0.4 synopsis:            Extensible Records -- description: license:             MIT@@ -19,19 +19,31 @@   location: https://github.com/VinylRecords/Vinyl/  library-  exposed-modules:     Data.Vinyl, Data.Vinyl.Field, Data.Vinyl.Lens,-                       Data.Vinyl.Witnesses, Data.Vinyl.Rec,-                       Data.Vinyl.Relation, Data.Vinyl.Unicode,-                       Data.Vinyl.Classes, Data.Vinyl.Idiom.Validation,-                       Data.Vinyl.Idiom.Identity, Data.Vinyl.Idiom.LazyIdentity-  build-depends:       base >=4.6 && <= 5, ghc-prim+  exposed-modules:     Data.Vinyl+                     , Data.Vinyl.Core+                     , Data.Vinyl.Operators+                     , Data.Vinyl.Lens+                     , Data.Vinyl.Witnesses+                     , Data.Vinyl.Constraint+                     , Data.Vinyl.Idiom.Validation+                     , Data.Vinyl.Idiom.Identity+                     , Data.Vinyl.Idiom.Thunk+                     , Data.Vinyl.TyFun+                     , Data.Vinyl.Functor+                     , Data.Vinyl.Universe+                     , Data.Vinyl.Universe.Id+                     , Data.Vinyl.Universe.Const+                     , Data.Vinyl.Universe.Field+                     , Data.Vinyl.TH+  build-depends:       base >=4.6 && <= 5, ghc-prim, template-haskell == 2.9.0.0   default-language:    Haskell2010+  ghc-options: -fwarn-dodgy-exports -fwarn-dodgy-imports -fwarn-unused-matches -fwarn-unused-imports -fwarn-unused-binds -fwarn-incomplete-record-updates -fwarn-missing-signatures -fwarn-name-shadowing -fwarn-orphans -fwarn-overlapping-patterns -fwarn-tabs -fwarn-type-defaults  benchmark bench-builder-all   type:             exitcode-stdio-1.0   hs-source-dirs:   benchmarks   main-is:          StorableBench.hs-  build-depends:    base >= 4.6 && <= 5, vector, criterion, vinyl == 0.3, mwc-random, lens, linear+  build-depends:    base >= 4.6 && <= 5, vector, criterion, vinyl == 0.4, mwc-random, lens, linear   ghc-options:      -O2 -fllvm   default-language: Haskell2010 @@ -39,5 +51,5 @@   type:             exitcode-stdio-1.0   hs-source-dirs:   tests   main-is:          Intro.lhs-  build-depends:    base >= 4.6 && <= 5, lens, vinyl == 0.3, doctest >= 0.8+  build-depends:    base >= 4.6 && <= 5, lens, vinyl == 0.4, doctest >= 0.8, singletons == 1.0   default-language: Haskell2010