packages feed

extensible 0.4.7.1 → 0.4.7.2

raw patch · 7 files changed

+162/−84 lines, 7 filesdep +aesondep +bytestringdep +cassavaPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: aeson, bytestring, cassava, text, unordered-containers

API changes (from Hackage documentation)

- Data.Extensible.Dictionary: instance forall k (h :: k -> *) (xs :: [k]). Data.Extensible.Dictionary.WrapForall GHC.Base.Monoid h xs => GHC.Base.Monoid (h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall k (h :: k -> *) (xs :: [k]). (Data.Extensible.Dictionary.WrapForall Data.Semigroup.Semigroup h xs, Data.Extensible.Dictionary.WrapForall GHC.Base.Monoid h xs) => GHC.Base.Monoid (h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall k (h :: k -> *) (xs :: [k]). Data.Extensible.Dictionary.WrapForall Data.Csv.Conversion.FromField h xs => Data.Csv.Conversion.FromRecord (h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall k (h :: k -> *) (xs :: [k]). Data.Extensible.Dictionary.WrapForall Data.Csv.Conversion.ToField h xs => Data.Csv.Conversion.ToRecord (h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall v (h :: v -> *) (xs :: [Data.Extensible.Internal.Assoc GHC.Types.Symbol v]). Data.Extensible.Class.Forall (Data.Extensible.Field.KeyValue GHC.TypeLits.KnownSymbol (Data.Extensible.Dictionary.Instance1 Data.Aeson.Types.FromJSON.FromJSON h)) xs => Data.Aeson.Types.FromJSON.FromJSON (Data.Extensible.Field.Field h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall v (h :: v -> *) (xs :: [Data.Extensible.Internal.Assoc GHC.Types.Symbol v]). Data.Extensible.Class.Forall (Data.Extensible.Field.KeyValue GHC.TypeLits.KnownSymbol (Data.Extensible.Dictionary.Instance1 Data.Aeson.Types.ToJSON.ToJSON h)) xs => Data.Aeson.Types.ToJSON.ToJSON (Data.Extensible.Field.Field h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall v (h :: v -> *) (xs :: [Data.Extensible.Internal.Assoc GHC.Types.Symbol v]). Data.Extensible.Class.Forall (Data.Extensible.Field.KeyValue GHC.TypeLits.KnownSymbol (Data.Extensible.Dictionary.Instance1 Data.Csv.Conversion.FromField h)) xs => Data.Csv.Conversion.FromNamedRecord (Data.Extensible.Field.Field h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Dictionary: instance forall v (h :: v -> *) (xs :: [Data.Extensible.Internal.Assoc GHC.Types.Symbol v]). Data.Extensible.Class.Forall (Data.Extensible.Field.KeyValue GHC.TypeLits.KnownSymbol (Data.Extensible.Dictionary.Instance1 Data.Csv.Conversion.ToField h)) xs => Data.Csv.Conversion.ToNamedRecord (Data.Extensible.Field.Field h Data.Extensible.Struct.:* xs)
+ Data.Extensible.Field: class (pk (AssocKey kv)) => KeyIs pk kv
+ Data.Extensible.Field: class (pv (AssocValue kv)) => ValueIs pv kv
+ Data.Extensible.Field: instance forall k v (h :: v -> *) (kv :: Data.Extensible.Internal.Assoc k v). Data.Aeson.Types.FromJSON.FromJSON (h (Data.Extensible.Field.AssocValue kv)) => Data.Aeson.Types.FromJSON.FromJSON (Data.Extensible.Field.Field h kv)
+ Data.Extensible.Field: instance forall k v (h :: v -> *) (kv :: Data.Extensible.Internal.Assoc k v). Data.Aeson.Types.ToJSON.ToJSON (h (Data.Extensible.Field.AssocValue kv)) => Data.Aeson.Types.ToJSON.ToJSON (Data.Extensible.Field.Field h kv)
+ Data.Extensible.Field: instance forall k v (h :: v -> *) (kv :: Data.Extensible.Internal.Assoc k v). Data.Csv.Conversion.FromField (h (Data.Extensible.Field.AssocValue kv)) => Data.Csv.Conversion.FromField (Data.Extensible.Field.Field h kv)
+ Data.Extensible.Field: instance forall k v (h :: v -> *) (kv :: Data.Extensible.Internal.Assoc k v). Data.Csv.Conversion.ToField (h (Data.Extensible.Field.AssocValue kv)) => Data.Csv.Conversion.ToField (Data.Extensible.Field.Field h kv)
+ Data.Extensible.Field: instance forall k1 v1 (pv :: v1 -> GHC.Types.Constraint) (v2 :: v1) (k2 :: k1). pv v2 => Data.Extensible.Field.ValueIs pv (k2 'Data.Extensible.Internal.:> v2)
+ Data.Extensible.Field: instance forall v1 k1 (pk :: k1 -> GHC.Types.Constraint) (k2 :: k1) (v2 :: v1). pk k2 => Data.Extensible.Field.KeyIs pk (k2 'Data.Extensible.Internal.:> v2)
+ Data.Extensible.Field: proxyAssocValue :: proxy kv -> Proxy (AssocValue kv)
+ Data.Extensible.Nullable: instance forall k (h :: k -> *) (x :: k). Data.Semigroup.Semigroup (h x) => Data.Semigroup.Semigroup (Data.Extensible.Nullable.Nullable h x)

Files

.travis.yml view
@@ -1,6 +1,6 @@ # This Travis job script has been generated by a script via #-#   make_travis_yml_2.hs 'extensible.cabal'+#   runghc make_travis_yml_2.hs 'extensible.cabal' # # For more information, see https://github.com/hvr/multi-ghc-travis #@@ -24,6 +24,8 @@   - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar   - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx +  - rm -rfv $HOME/.cabal/packages/head.hackage+ matrix:   include:     - compiler: "ghc-7.10.3"@@ -35,61 +37,84 @@     - compiler: "ghc-8.2.1"     # env: TEST=--disable-tests BENCH=--disable-benchmarks       addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.2.1], sources: [hvr-ghc]}}+    - compiler: "ghc-8.4.1"+      env: GHCHEAD=true+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.4.1], sources: [hvr-ghc]}}  before_install:- - HC=${CC}- - HCPKG=${HC/ghc/ghc-pkg}- - unset CC- - PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$PATH- - PKGNAME='extensible'+  - HC=${CC}+  - HCPKG=${HC/ghc/ghc-pkg}+  - unset CC+  - ROOTDIR=$(pwd)+  - mkdir -p $HOME/.local/bin+  - "PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$HOME/local/bin:$PATH"+  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))+  - echo $HCNUMVER  install:- - cabal --version- - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"- - BENCH=${BENCH---enable-benchmarks}- - TEST=${TEST---enable-tests}- - HADDOCK=${HADDOCK-true}- - INSTALLED=${INSTALLED-true}- - travis_retry cabal update -v- - sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config- - rm -fv cabal.project.local- - "echo 'packages: .' > cabal.project"- - rm -f cabal.project.freeze- - cabal new-build -w ${HC} ${TEST} ${BENCH} --dep -j2 all- - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --dep -j2 all+  - cabal --version+  - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"+  - BENCH=${BENCH---enable-benchmarks}+  - TEST=${TEST---enable-tests}+  - HADDOCK=${HADDOCK-true}+  - INSTALLED=${INSTALLED-true}+  - GHCHEAD=${GHCHEAD-false}+  - travis_retry cabal update -v+  - "sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"+  - rm -fv cabal.project cabal.project.local+  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage+  - |+    if $GHCHEAD; then+      sed -i.bak 's/-- allow-newer:.*/allow-newer: *:base, *:template-haskell, *:ghc, *:Cabal/' ${HOME}/.cabal/config +      echo 'repository head.hackage'                                                        >> ${HOME}/.cabal/config+      echo '   url: http://head.hackage.haskell.org/'                                       >> ${HOME}/.cabal/config+      echo '   secure: True'                                                                >> ${HOME}/.cabal/config+      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> ${HOME}/.cabal/config+      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> ${HOME}/.cabal/config+      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> ${HOME}/.cabal/config+      echo '   key-threshold: 3'                                                            >> ${HOME}/.cabal.config++      cabal new-update head.hackage -v+    fi+  - grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'+  - "printf 'packages: \".\"\\n' > cabal.project"+  - cat cabal.project+  - if [ -f "./configure.ac" ]; then+      (cd "." && autoreconf -i);+    fi+  - rm -f cabal.project.freeze+  - cabal new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dep -j2 all+  - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project" --dep -j2 all+  - rm -rf .ghc.environment.* "."/dist+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)+ # Here starts the actual work to be performed for the package under test; # any command which exits with a non-zero exit code causes the build to fail. script:- - if [ -f configure.ac ]; then autoreconf -i; fi- - rm -rf .ghc.environment.* dist/- - cabal sdist # test that a source-distribution can be generated- - cd dist/- - SRCTAR=(${PKGNAME}-*.tar.gz)- - SRC_BASENAME="${SRCTAR/%.tar.gz}"- - tar -xvf "./$SRC_BASENAME.tar.gz"- - cd "$SRC_BASENAME/"-## from here on, CWD is inside the extracted source-tarball- - rm -fv cabal.project.local- - "echo 'packages: .' > cabal.project"- # this builds all libraries and executables (without tests/benchmarks)- - rm -f cabal.project.freeze- - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all- # this builds all libraries and executables (including tests/benchmarks)- # - rm -rf ./dist-newstyle+  # test that source-distributions can be generated+  - (cd "." && cabal sdist)+  - mv "."/dist/extensible-*.tar.gz ${DISTDIR}/+  - cd ${DISTDIR} || false+  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;+  - "printf 'packages: extensible-*/*.cabal\\n' > cabal.project"+  - cat cabal.project+  # this builds all libraries and executables (without tests/benchmarks)+  - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all - # Build with installed constraints for packages in global-db- - if $INSTALLED; then-     echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh;-   else echo "Not building with installed constraints"; fi+  # Build with installed constraints for packages in global-db+  - if $INSTALLED; then echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks $(${HCPKG} list --global --simple-output --names-only | sed 's/\([a-zA-Z0-9-]\{1,\}\) */--constraint="\1 installed" /g') all | sh; else echo "Not building with installed constraints"; fi - # build & run tests, build benchmarks- - cabal new-build -w ${HC} ${TEST} ${BENCH} all- - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} all; fi+  # build & run tests, build benchmarks+  - cabal new-build -w ${HC} ${TEST} ${BENCH} all+  - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} ${BENCH} all; fi - # haddock- - rm -rf ./dist-newstyle- - if $HADDOCK; then cabal new-haddock -w ${HC} --disable-tests --disable-benchmarks all; else echo "Skipping haddock generation";fi+  # cabal check+  - (cd extensible-* && cabal check)++  # haddock+  - rm -rf ./dist-newstyle+  - if $HADDOCK; then cabal new-haddock -w ${HC} ${TEST} ${BENCH} all; else echo "Skipping haddock generation";fi  # REGENDATA ["extensible.cabal"] # EOF
CHANGELOG.md view
@@ -1,3 +1,9 @@+0.4.7.2+-------------------------------------------------+* Added cassava's `ToNamedRecord`, `ToRecord`, `FromNamedRecord` and `FromRecord` instances+* Added `KeyIs` and `ValueIs`+* Added `FromJSON` and `ToJSON` instances for `(:*)`+ 0.4.7.1 ------------------------------------------------- * Fixed weird CPP errors on macOS 10.13.2 (#18)
− examples/aeson.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-import Data.Aeson hiding (KeyValue)-import Data.Constraint-import Data.Extensible-import Data.Monoid-import Data.Proxy-import Data.String (fromString)-import GHC.TypeLits (KnownSymbol, symbolVal)-import qualified Data.HashMap.Strict as HM--instance Forall (KeyValue KnownSymbol FromJSON) xs => FromJSON (Record xs) where-  parseJSON = withObject "Object" $ \v -> hgenerateFor (Proxy :: Proxy (KeyValue KnownSymbol FromJSON))-    $ \m -> let k = symbolVal (proxyAssocKey m) in case HM.lookup (fromString k) v of-      Just a -> Field <$> return <$> parseJSON a-      Nothing -> fail $ "Missing key: " ++ k--instance Forall (KeyValue KnownSymbol ToJSON) xs => ToJSON (Record xs) where-  toJSON rec = Object $ HM.fromList $ flip appEndo [] $ hfoldMap getConst'-    $ hzipWith (\(Comp Dict) v -> Const' $ Endo-      ((fromString $ symbolVal $ proxyAssocKey v, toJSON $ getField v):))-    (library :: Comp Dict (KeyValue KnownSymbol ToJSON) :* xs) rec
extensible.cabal view
@@ -1,9 +1,12 @@ name:                extensible-version:             0.4.7.1+version:             0.4.7.2 synopsis:            Extensible, efficient, optics-friendly data types and effects homepage:            https://github.com/fumieval/extensible bug-reports:         http://github.com/fumieval/extensible/issues-description:         Poly-kinded extensible records, variants, effects, tangles+description:+    This package provides a powerful framework to combine and manipulate various types of structures.+    .+    See also <https://www.schoolofhaskell.com/user/fumieval/extensible School of Haskell> for tutorials. license:             BSD3 license-file:        LICENSE author:              Fumiaki Kinoshita@@ -12,7 +15,7 @@ category:            Data, Records, Monads build-type:          Simple stability:           experimental-Tested-With:         GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1+Tested-With:         GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1, GHC == 8.4.1  extra-source-files:   examples/*.hs@@ -65,22 +68,27 @@     , PolyKinds     , CPP   build-depends:       base >= 4.8 && <5-    , template-haskell+    , aeson+    , bytestring+    , cassava+    , comonad     , constraints+    , deepseq     , ghc-prim+    , hashable+    , monad-skeleton >= 0.1.2+    , mtl     , primitive     , profunctors+    , QuickCheck     , semigroups-    , comonad-    , deepseq-    , hashable+    , StateVar     , tagged+    , template-haskell+    , text     , transformers+    , unordered-containers     , vector-    , mtl-    , monad-skeleton >= 0.1.2-    , StateVar-    , QuickCheck   hs-source-dirs:      src   ghc-options: -Wall   default-language:    Haskell2010
src/Data/Extensible/Dictionary.hs view
@@ -18,7 +18,11 @@ ----------------------------------------------------------------------- module Data.Extensible.Dictionary (library, WrapForall, Instance1) where import Control.DeepSeq+import qualified Data.Aeson as J+import qualified Data.Csv as Csv+import qualified Data.ByteString.Char8 as BC import Data.Extensible.Class+import Data.Extensible.Field import Data.Extensible.Product import Data.Extensible.Sum import Data.Extensible.Internal@@ -28,10 +32,14 @@ import Data.Extensible.Wrapper import Data.Functor.Identity import Data.Hashable+import qualified Data.HashMap.Strict as HM import Data.Semigroup import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Mutable as M import qualified Data.Vector.Unboxed as U+import qualified Data.Vector as V+import qualified Data.Text as T+import GHC.TypeLits import Test.QuickCheck.Arbitrary import Test.QuickCheck.Gen @@ -61,7 +69,7 @@     (library :: Comp Dict (Instance1 Semigroup h) :* xs)   {-# INLINE (<>) #-} -instance WrapForall Monoid h xs => Monoid (h :* xs) where+instance (WrapForall Semigroup h xs, WrapForall Monoid h xs) => Monoid (h :* xs) where   mempty = hrepeatFor (Proxy :: Proxy (Instance1 Monoid h)) mempty   {-# INLINE mempty #-}   mappend = hzipWith3 (\(Comp Dict) -> mappend)@@ -143,6 +151,37 @@   rnf xs = henumerateFor (Proxy :: Proxy (Instance1 NFData h)) (Proxy :: Proxy xs)     (\i -> deepseq (hlookup i xs)) ()   {-# INLINE rnf #-}++instance WrapForall Csv.FromField h xs => Csv.FromRecord (h :* xs) where+  parseRecord rec = hgenerateFor (Proxy :: Proxy (Instance1 Csv.FromField h))+    $ \i -> G.indexM rec (getMemberId i) >>= Csv.parseField++instance Forall (KeyValue KnownSymbol (Instance1 Csv.FromField h)) xs => Csv.FromNamedRecord (Field h :* xs) where+  parseNamedRecord rec = hgenerateFor (Proxy :: Proxy (KeyValue KnownSymbol (Instance1 Csv.FromField h)))+    $ \i -> rec Csv..: BC.pack (symbolVal (proxyAssocKey i)) >>= Csv.parseField++instance WrapForall Csv.ToField h xs => Csv.ToRecord (h :* xs) where+  toRecord = V.fromList+    . hfoldrWithIndexFor (Proxy :: Proxy (Instance1 Csv.ToField h))+      (\_ v -> (:) $ Csv.toField v) []++instance Forall (KeyValue KnownSymbol (Instance1 Csv.ToField h)) xs => Csv.ToNamedRecord (Field h :* xs) where+  toNamedRecord = hfoldlWithIndexFor (Proxy :: Proxy (KeyValue KnownSymbol (Instance1 Csv.ToField h)))+    (\k m v -> HM.insert (BC.pack (symbolVal (proxyAssocKey k))) (Csv.toField v) m)+    HM.empty++instance Forall (KeyValue KnownSymbol (Instance1 J.FromJSON h)) xs => J.FromJSON (Field h :* xs) where+  parseJSON = J.withObject "Object" $ \v -> hgenerateFor+    (Proxy :: Proxy (KeyValue KnownSymbol (Instance1 J.FromJSON h)))+    $ \m -> let k = symbolVal (proxyAssocKey m) in case HM.lookup (T.pack k) v of+      Just a -> Field <$> J.parseJSON a+      Nothing -> fail $ "Missing key: " ++ k++instance Forall (KeyValue KnownSymbol (Instance1 J.ToJSON h)) xs => J.ToJSON (Field h :* xs) where+  toJSON = J.Object . hfoldlWithIndexFor+    (Proxy :: Proxy (KeyValue KnownSymbol (Instance1 J.ToJSON h)))+    (\k m v -> HM.insert (T.pack (symbolVal (proxyAssocKey k))) (J.toJSON v) m)+    HM.empty  instance WrapForall Show h xs => Show (h :| xs) where   showsPrec d (EmbedAt i h) = showParen (d > 10) $ showString "EmbedAt "
src/Data/Extensible/Field.hs view
@@ -39,16 +39,21 @@   , AssocValue   , KeyValue   , proxyAssocKey+  , proxyAssocValue+  , KeyIs+  , ValueIs   -- * Internal   , LabelPhantom   , Labelling   , Inextensible   ) where import Control.DeepSeq (NFData)+import qualified Data.Aeson as J import Data.Coerce #if __GLASGOW_HASKELL__ < 802 import Data.Constraint #endif+import qualified Data.Csv as Csv import Data.Extensible.Class import Data.Extensible.Sum import Data.Extensible.Match@@ -80,6 +85,10 @@ proxyAssocKey :: proxy kv -> Proxy (AssocKey kv) proxyAssocKey _ = Proxy +-- | Proxy-level 'AssocKey'. This is useful when using 'symbolVal'.+proxyAssocValue :: proxy kv -> Proxy (AssocValue kv)+proxyAssocValue _ = Proxy+ -- | Take the type of the value type family AssocValue (kv :: Assoc k v) :: v where   AssocValue (k ':> v) = v@@ -89,6 +98,17 @@  instance (pk k, pv v) => KeyValue pk pv (k ':> v) +-- | Combined constraint for 'Assoc'+class (pk (AssocKey kv)) => KeyIs pk kv where++instance (pk k) => KeyIs pk (k ':> v)++-- | Combined constraint for 'Assoc'+class (pv (AssocValue kv)) => ValueIs pv kv where++instance (pv v) => ValueIs pv (k ':> v)++ -- | A @'Field' h (k ':> v)@ is @h v@ annotated with the field name @k@. -- -- @'Field' :: (v -> *) -> Assoc k v -> *@@@ -121,6 +141,10 @@ ND_Field(NFData) ND_Field(Arbitrary) ND_Field(Hashable)+ND_Field(Csv.FromField)+ND_Field(Csv.ToField)+ND_Field(J.FromJSON)+ND_Field(J.ToJSON)  newtype instance U.MVector s (Field h x) = MV_Field (U.MVector s (h (AssocValue x))) newtype instance U.Vector (Field h x) = V_Field (U.Vector (h (AssocValue x)))
src/Data/Extensible/Nullable.hs view
@@ -39,6 +39,9 @@   type Repr (Nullable h) x = Maybe (Repr h x)   _Wrapper = withIso _Wrapper $ \f g -> dimap (fmap f . getNullable) (fmap (Nullable . fmap g)) +instance Semigroup (h x) => Semigroup (Nullable h x) where+  (<>) = mappend+ instance Semigroup (h x) => Monoid (Nullable h x) where   mempty = Nullable Nothing   mappend (Nullable (Just a)) (Nullable (Just b)) = Nullable (Just (a <> b))