packages feed

vinyl 0.5 → 0.5.1

raw patch · 6 files changed

+104/−30 lines, 6 filesdep ~vinylnew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: vinyl

API changes (from Hackage documentation)

+ Data.Vinyl.Derived: (=:) :: KnownSymbol s => proxy '(s, a) -> a -> FieldRec '['(s, a)]
+ Data.Vinyl.Derived: SField :: SField
+ Data.Vinyl.Derived: data SField (field :: k)
+ Data.Vinyl.Derived: fieldMap :: (a -> b) -> ElField '(s, a) -> ElField '(s, b)
+ Data.Vinyl.Derived: getField :: ElField '(s, t) -> t
+ Data.Vinyl.Derived: instance (KnownSymbol s, Storable t) => Storable (ElField '(s, t))
+ Data.Vinyl.Derived: instance Eq (SField a)
+ Data.Vinyl.Derived: instance Eq t => Eq (ElField '(s, t))
+ Data.Vinyl.Derived: instance KnownSymbol s => Show (SField '(s, t))
+ Data.Vinyl.Derived: instance Ord (SField a)
+ Data.Vinyl.Derived: instance Ord t => Ord (ElField '(s, t))
+ Data.Vinyl.Derived: instance Show t => Show (ElField '(s, t))
+ Data.Vinyl.Derived: rfield :: Functor f => (a -> f b) -> ElField '(s, a) -> f (ElField '(s, b))
- Data.Vinyl.Derived: Field :: t -> ElField '(s, t)
+ Data.Vinyl.Derived: Field :: !t -> ElField '(s, t)

Files

+ CHANGELOG.md view
@@ -0,0 +1,27 @@+0.5.1+---------++Added utilities for working with the `FieldRec` type.++Vinyl 0.5+=========++Vinyl 0.5 combines the generality of Vinyl 0.4 with the ease-of-use of previous+versions by eschewing the defunctionalized type families and just using plain+type constructors; Vinyl 0.4-style records can be recovered in most cases in a+modular manner without baking it into the fabric of Vinyl itself.++Also new in 0.5 is a unified lens-based approach to subtyping, coercion and+projection.++Vinyl 0.4+=========++Vinyl 0.4 is a big departure from previous versions, in that it introduces a+universe encoding as a means to generalize the space of keys from strings to+any arbitrary space. This means that you can have closed universes for your+records.++For details on how to use the new Vinyl, please see `tests/Intro.lhs` or view+Jon's talk at BayHac 2014, [Programming in+Vinyl](http://www.jonmsterling.com/posts/2014-05-19-programming-in-vinyl-bayhac.html).
Data/Vinyl/Core.hs view
@@ -119,6 +119,7 @@   -> h (Rec g rs) rtraverse _ RNil      = pure RNil rtraverse f (x :& xs) = (:&) <$> f x <*> rtraverse f xs+{-# INLINABLE rtraverse #-}  -- | A record with uniform fields may be turned into a list. recordToList@@ -154,7 +155,7 @@ instance RecAll f rs Show => Show (Rec f rs) where   show xs =     (\str -> "{" <> str <> "}")-      . intercalate "; "+      . intercalate ", "       . recordToList       . rmap (\(Compose (Dict x)) -> Const $ show x)       $ reifyConstraint (Proxy :: Proxy Show) xs
Data/Vinyl/Derived.hs view
@@ -1,18 +1,63 @@ {-# LANGUAGE DataKinds  #-}+{-# LANGUAGE FlexibleInstances  #-} {-# LANGUAGE GADTs      #-} {-# LANGUAGE PolyKinds  #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}  module Data.Vinyl.Derived where +import Data.Proxy import Data.Vinyl.Core import Data.Vinyl.Functor-+import Foreign.Ptr (castPtr)+import Foreign.Storable import GHC.TypeLits  data ElField (field :: (Symbol, *)) where-  Field :: KnownSymbol s => t -> ElField '(s,t)+  Field :: KnownSymbol s => !t -> ElField '(s,t)  type FieldRec = Rec ElField type HList = Rec Identity type LazyHList = Rec Thunk++deriving instance Eq t => Eq (ElField '(s,t))+deriving instance Ord t => Ord (ElField '(s,t))++instance Show t => Show (ElField '(s,t)) where+  show (Field x) = (symbolVal (Proxy::Proxy s))++" :-> "++show x++-- | Get the data payload of an 'ElField'.+getField :: ElField '(s,t) -> t+getField (Field x) = x++-- | 'ElField' is isomorphic to a functor something like @Compose+-- ElField ('(,) s)@.+fieldMap :: (a -> b) -> ElField '(s,a) -> ElField '(s,b)+fieldMap f (Field x) = Field (f x)+{-# INLINE fieldMap #-}++-- | Lens for an 'ElField''s data payload.+rfield :: Functor f => (a -> f b) -> ElField '(s,a) -> f (ElField '(s,b))+rfield f (Field x) = fmap Field (f x)+{-# INLINE rfield #-}++-- | Shorthand for a 'FieldRec' with a single field.+(=:) :: KnownSymbol s => proxy '(s,a) -> a -> FieldRec '[ '(s,a) ]+(=:) _ x = Field x :& RNil++-- | A proxy for field types.+data SField (field :: k) = SField++instance Eq (SField a) where _ == _ = True+instance Ord (SField a) where compare _ _ = EQ+instance KnownSymbol s => Show (SField '(s,t)) where+  show _ = "SField "++symbolVal (Proxy::Proxy s)++instance forall s t. (KnownSymbol s, Storable t)+    => Storable (ElField '(s,t)) where+  sizeOf _ = sizeOf (undefined::t)+  alignment _ = alignment (undefined::t)+  peek ptr = Field `fmap` peek (castPtr ptr)+  poke ptr (Field x) = poke (castPtr ptr) x
benchmarks/StorableBench.hs view
@@ -11,10 +11,10 @@ import Control.Lens import Control.Monad (when) import qualified Data.Foldable as F+import Data.Proxy import qualified Data.Vector.Storable as V import qualified Data.Vector.Storable.Mutable as VM import Data.Vinyl-import Data.Vinyl.Universe.Field import Foreign.Ptr (castPtr) import Foreign.Storable (Storable(..)) import Linear (V2, V3, _y)@@ -28,23 +28,23 @@ randVecStd :: (Storable a, Variate a) => Int -> IO (V.Vector a) randVecStd = withSystemRandom . randVec -vNorm :: SField ("normal" ::: V3 a)-vNorm = SField+vNorm :: Proxy '("normal", V3 a)+vNorm = Proxy -type MyFields a = [ "pos" ::: V3 a, "tex" ::: V2 a, "normal" ::: V3 a ]-type MyVertex a = PlainRec ElField (MyFields a)+type MyFields a = [ '("pos", V3 a), '("tex", V2 a), '("normal", V3 a) ]+type MyVertex a = FieldRec (MyFields a)  doubleNviL :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)-doubleNviL = V.map (rLens vNorm . _y *~ (2::Float))+doubleNviL = V.map (rlens vNorm . rfield . _y *~ (2::Float))  vinylNSumL :: (Num a, Storable a) => V.Vector (MyVertex a) -> a-vinylNSumL = V.sum . V.map (F.sum . view (rLens vNorm))+vinylNSumL = V.sum . V.map (F.sum . view (rlens vNorm . rfield))  doubleNvi :: V.Vector (MyVertex Float) -> V.Vector (MyVertex Float)-doubleNvi = V.map (rMod vNorm (_y *~ (2::Float)))+doubleNvi = V.map (rlens vNorm . rfield . _y *~ (2::Float))  vinylNSum :: (Num a, Storable a) => V.Vector (MyVertex a) -> a-vinylNSum = V.sum . V.map (F.sum . rGet vNorm)+vinylNSum = V.sum . V.map (F.sum . view rfield . rget vNorm)  main :: IO () main = do vals <- randVecStd $ n * 8 :: IO (V.Vector Float)
tests/Intro.lhs view
@@ -47,31 +47,31 @@ > instance Show (Attr Sleeping) where show (Attr x) = "sleeping: " ++ show x > instance Show (Attr Master) where show (Attr x) = "master: " ++ show x -> (=:) :: sing f -> ElF f -> Attr f-> _ =: x = Attr x+> (=::) :: sing f -> ElF f -> Attr f+> _ =:: x = Attr x  > genSingletons [ ''Fields ]  Now, let’s try to make an entity that represents a man: -> jon = (SName =: "jon")->    :& (SAge =: 23)->    :& (SSleeping =: False)+> jon = (SName =:: "jon")+>    :& (SAge =:: 23)+>    :& (SSleeping =:: False) >    :& RNil  Automatically, we can show the record:  > -- | > -- >>> show jon-> -- "{name: \"jon\"; age: 23; sleeping: False}"+> -- "{name: \"jon\", age: 23, sleeping: False}"  And its types are all inferred with no problem. Now, make a dog! Dogs are life-forms, but unlike men, they have masters. So, let’s build my dog: -> tucker = (SName =: "tucker")->       :& (SAge =: 9)->       :& (SSleeping =: True)->       :& (SMaster =: jon)+> tucker = (SName =:: "tucker")+>       :& (SAge =:: 9)+>       :& (SSleeping =:: True)+>       :& (SMaster =:: jon) >       :& RNil  Using Lenses@@ -85,7 +85,7 @@   > wakeUp :: (Sleeping ∈ fields) => Rec Attr fields -> Rec Attr fields-> wakeUp = rput $ SSleeping =: False+> wakeUp = rput $ SSleeping =:: 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@@ -110,7 +110,7 @@ update on a record:  > masterSleeping = rlens SMaster . unAttr . rlens SSleeping-> tucker'' = masterSleeping .~ (SSleeping =: True) $ tucker'+> tucker'' = masterSleeping .~ (SSleeping =:: True) $ tucker'  > -- | >>> tucker'' ^. masterSleeping > -- sleeping: True@@ -169,18 +169,18 @@ left-accumulating `Validation` type.  > goodPerson :: Rec Attr Person-> goodPerson = (SName =: "Jon")->           :& (SAge =: 20)+> goodPerson = (SName =:: "Jon")+>           :& (SAge =:: 20) >           :& RNil -> badPerson = (SName =: "J#@#$on")->           :& (SAge =: 20)+> badPerson = (SName =:: "J#@#$on")+>           :& (SAge =:: 20) >           :& RNil  We'll give validation a (rather poor) shot.  > validatePerson :: Rec Attr Person -> Maybe (Rec Attr Person)-> validatePerson p = (\n a -> (SName =: n) :& (SAge =: a) :& RNil) <$> vName <*> vAge where+> validatePerson p = (\n a -> (SName =:: n) :& (SAge =:: a) :& RNil) <$> vName <*> vAge where >   vName = validateName $ p ^. rlens SName . unAttr >   vAge  = validateAge $ p ^. rlens SAge . unAttr >
vinyl.cabal view
@@ -1,5 +1,5 @@ name:                vinyl-version:             0.5+version:             0.5.1 synopsis:            Extensible Records -- description: license:             MIT@@ -11,6 +11,7 @@ stability:           Experimental build-type:          Simple cabal-version:       >=1.10+extra-source-files:  CHANGELOG.md  description: Extensible records for Haskell with lenses using modern GHC features.