packages feed

large-anon 0.2 → 0.2.1

raw patch · 6 files changed

+104/−15 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Record.Anon.Advanced: distribute :: (Functor m, KnownFields r) => m (Record f r) -> Record (m :.: f) r
+ Data.Record.Anon.Advanced: distribute' :: (Functor m, KnownFields r) => m (Record I r) -> Record m r

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for large-anon +## 0.2.1 -- 2023-07-05++* Add `distribute` (Johannes Gerer, #142)+ ## 0.2 -- 2023-03-06  * Do not generate imports in the plugin (#129).
large-anon.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               large-anon-version:            0.2+version:            0.2.1 synopsis:           Scalable anonymous records description:        The @large-anon@ package provides support for anonymous                     records in Haskell, with a focus on compile-time (and@@ -12,7 +12,7 @@ category:           Records extra-source-files: CHANGELOG.md                     test/Test/Sanity/RebindableSyntax/Tests.hs-tested-with:        GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.7 || ==9.4.4+tested-with:        GHC ==8.8.4 || ==8.10.7 || ==9.0.2 || ==9.2.7 || ==9.4.5  library   exposed-modules:
src/Data/Record/Anon/Advanced.hs view
@@ -48,6 +48,8 @@   , cmapM   , sequenceA   , sequenceA'+  , distribute+  , distribute'     -- ** Zipping   , zip   , zipWith@@ -412,6 +414,23 @@ -- | Simplified form of 'sequenceA' sequenceA' :: Applicative m => Record m r -> m (Record I r) sequenceA' = A.sequenceA'++-- | Distribute+--+-- This is a higher kinded version of @distribute@ from+-- <https://hackage.haskell.org/package/distributive>, and inverse to+-- 'sequenceA'.+--+-- Be careful with this function: if @f@ allows effects, then those effects will+-- be duplicated whenever any field of the resulting record is accessed. Using+-- this with @f == Vector@ or @f == Maybe@ is fine, but you almost certainly+-- don't want to use it with @f == IO@, for example.+distribute :: (Functor m, KnownFields r) => m (Record f r) -> Record (m :.: f) r+distribute = A.distribute++-- | Simplified form of 'distribute'.+distribute' :: (Functor m, KnownFields r) => m (Record I r) -> Record m r+distribute' = A.distribute'  -- | Analogue of 'Prelude.zip' zip :: Record f r -> Record g r -> Record (Product f g) r
src/Data/Record/Anon/Internal/Advanced.hs view
@@ -53,6 +53,8 @@   , cmapM   , sequenceA   , sequenceA'+  , distribute+  , distribute'     -- ** Zipping   , zip   , zipWith@@ -339,6 +341,27 @@ sequenceA' = sequenceA . co   where     co :: Record m r -> Record (m :.: I) r+    co = noInlineUnsafeCo++distribute :: forall r m f.+     (Functor m, KnownFields r)+  => m (Record f r) -> Record (m :.: f) r+distribute =+      unsafeFromCanonical+    . Canon.fromList+    . (\cs -> fieldVec cs <$> indices)+    . fmap toCanonical+  where+    indices :: [Int]+    indices = [0 .. pred (length $ proxy fieldNames (Proxy @r))]++    fieldVec :: m (Canonical f) -> Int -> (m :.: f) Any+    fieldVec cs idx = Comp $ flip Canon.getAtIndex idx <$> cs++distribute' :: (Functor m, KnownFields r) => m (Record I r) -> Record m r+distribute' = co . distribute+  where+    co :: Record (m :.: I) r -> Record m r     co = noInlineUnsafeCo  pure :: forall f r. KnownFields r => (forall x. f x) -> Record f r
test/Test/Prop/Record/Combinators/Simple.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE GADTs            #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeOperators    #-}-{-# LANGUAGE ViewPatterns     #-}+{-# LANGUAGE DeriveFunctor       #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications    #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}  module Test.Prop.Record.Combinators.Simple (tests) where @@ -9,6 +11,7 @@ import Data.Bifunctor import Data.SOP +import qualified Data.Record.Anon          as Anon import qualified Data.Record.Anon.Advanced as Anon  import Test.Tasty@@ -21,15 +24,16 @@  tests :: TestTree tests = testGroup "Test.Prop.Record.Combinators.Simple" [-      testProperty "map"       test_map-    , testProperty "mapM"      test_mapM-    , testProperty "zip"       test_zip-    , testProperty "zipWith"   test_zipWith-    , testProperty "zipWithM"  test_zipWithM-    , testProperty "collapse"  test_collapse-    , testProperty "sequenceA" test_sequenceA-    , testProperty "pure"      test_pure-    , testProperty "ap"        test_ap+      testProperty "map"        test_map+    , testProperty "mapM"       test_mapM+    , testProperty "zip"        test_zip+    , testProperty "zipWith"    test_zipWith+    , testProperty "zipWithM"   test_zipWithM+    , testProperty "collapse"   test_collapse+    , testProperty "sequenceA"  test_sequenceA+    , testProperty "pure"       test_pure+    , testProperty "ap"         test_ap+    , testProperty "distribute" test_distribute     ]  {-------------------------------------------------------------------------------@@ -39,6 +43,13 @@ pTop :: Proxy Top pTop = Proxy +data Pair a = MkPair a a+  deriving (Show, Eq, Functor)++instance Applicative Pair where+  pure x = MkPair x x+  MkPair f1 f2 <*> MkPair x1 x2 = MkPair (f1 x1) (f2 x2)+ {-------------------------------------------------------------------------------   Tests proper -------------------------------------------------------------------------------}@@ -141,3 +152,27 @@      f :: K Int x -> (K Int -.-> K Int) x     f (K x) = fn $ \(K y) -> K (x + y)++-- | Test 'Anon.distribute'+--+-- We do not have a model implementation, but instead test that+-- 'Anon.distribute' is right inverse to 'Anon.sequenceA'.+test_distribute ::+     SomeRecordPair (K Int) (K Int)+  -> Property+test_distribute = \(SR2 fields r1 r2) ->+    Modl.fieldsKnown fields $+      go fields r1 r2+  where+    go :: forall r.+         Anon.KnownFields r+      => Modl.ModelFields r+      -> Modl.ModelRecord (K Int) r+      -> Modl.ModelRecord (K Int) r+      -> Property+    go fields r1 r2 =+            rs+        === Anon.sequenceA (Anon.distribute rs)+      where+        rs :: Pair (Anon.Record (K Int) r)+        rs = MkPair (Modl.toRecord fields r1) (Modl.toRecord fields r2)
test/Test/Prop/Record/Model.hs view
@@ -34,6 +34,7 @@     -- * Constraints   , ModelSatisfies   , satisfyAll+  , fieldsKnown     -- * Conversion to/from 'Record'   , toRecord   , fromRecord@@ -70,6 +71,7 @@  import Data.Record.Anon import Data.Record.Anon.Advanced (Record)+ import qualified Data.Record.Anon.Advanced as Anon  {-------------------------------------------------------------------------------@@ -122,6 +124,12 @@ satisfyAll _ MF1  k = k satisfyAll _ MF2  k = k satisfyAll _ MF2' k = k++fieldsKnown :: ModelFields r -> (KnownFields r => a) -> a+fieldsKnown MF0  k = k+fieldsKnown MF1  k = k+fieldsKnown MF2  k = k+fieldsKnown MF2' k = k  {-------------------------------------------------------------------------------   Conversion from/to model