packages feed

pa-label 0.1.0.1 → 0.1.1.0

raw patch · 3 files changed

+116/−14 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Label: unzipT2 :: forall l1 t1 l2 t2. [T2 l1 t1 l2 t2] -> T2 l1 [t1] l2 [t2]
+ Label: unzipT3 :: forall l1 t1 l2 t2 l3 t3. [T3 l1 t1 l2 t2 l3 t3] -> T3 l1 [t1] l2 [t2] l3 [t3]
+ Label: zipT2 :: forall l1 l2 t1 t2. (HasField l1 (T2 l1 [t1] l2 [t2]) [t1], HasField l2 (T2 l1 [t1] l2 [t2]) [t2]) => T2 l1 [t1] l2 [t2] -> [T2 l1 t1 l2 t2]
+ Label: zipT3 :: forall l1 l2 t1 t2 l3 t3. (HasField l1 (T3 l1 [t1] l2 [t2] l3 [t3]) [t1], HasField l2 (T3 l1 [t1] l2 [t2] l3 [t3]) [t2], HasField l3 (T3 l1 [t1] l2 [t2] l3 [t3]) [t3]) => T3 l1 [t1] l2 [t2] l3 [t3] -> [T3 l1 t1 l2 t2 l3 t3]

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for pa-label +## 0.1.1.0 -- 2024-03-18++* Add `zipT2/zipT3`, `unzipT2/unzipT3`+ ## 0.1.0.0 -- 2023-05-19  * First version; contains the `Label` type, `T2`/`T3`, `E2`/`E3`, and some helpers.
pa-label.cabal view
@@ -1,28 +1,75 @@ cabal-version:      3.0+-- !!! ATTN: file autogenerated from pa-template.cabal.mustache on toplevel !!! name:               pa-label-version:            0.1.0.1+version:            0.1.1.0 synopsis:           Labels, and labelled tuples and enums (GHC >9.2)-description:+description:         license:            BSD-3-Clause license-file:       LICENSE -- author: maintainer:         Philip Patsch <philip.patsch@possehl-analytics.com> copyright:          2023 Possehl Analytics GmbH homepage:           https://github.com/possehl-analytics/pa-hackage-category:           Data, possehl-analytics+category:           Data, Possehl-Analytics build-type:         Simple extra-doc-files:    CHANGELOG.md                     README.md -- extra-source-files: -common warnings-    ghc-options: -Wall +common common-options+  ghc-options:+      -Wall+      -Wno-type-defaults+      -Wunused-packages+      -Wredundant-constraints+      -fwarn-missing-deriving-strategies++  -- See https://downloads.haskell.org/ghc/latest/docs/users_guide/exts.html+  -- for a description of all these extensions+  default-extensions:+      -- Infer Applicative instead of Monad where possible+    ApplicativeDo++    -- Allow literal strings to be Text+    OverloadedStrings++    -- Syntactic sugar improvements+    LambdaCase+    MultiWayIf++    -- Makes the (deprecated) usage of * instead of Data.Kind.Type an error+    NoStarIsType++    -- Convenient and crucial to deal with ambiguous field names, commonly+    -- known as RecordDotSyntax+    OverloadedRecordDot++    -- does not export record fields as functions, use OverloadedRecordDot to access instead+    NoFieldSelectors++    -- Record punning+    RecordWildCards++    -- Improved Deriving+    DerivingStrategies+    DerivingVia++    -- Type-level strings+    DataKinds++    -- to enable the `type` keyword in import lists (ormolu uses this automatically)+    ExplicitNamespaces++  default-language: GHC2021+ library-    import:           warnings-    exposed-modules:  Label+    import:           common-options+    exposed-modules:+      Label,     -- other-modules:     -- other-extensions:-    build-depends:    base <5     hs-source-dirs:   src-    default-language: GHC2021+    build-depends:+      base <5,+
src/Label.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE DerivingStrategies #-}  module Label   ( -- * Labels@@ -16,9 +15,13 @@     focusOnField,     monoMapT2,     tupleToT2,+    zipT2,+    unzipT2,     T3 (..),     monoMapT3,     tupleToT3,+    zipT3,+    unzipT3,      -- * Named Sums/Enums     E2 (..),@@ -91,7 +94,7 @@   getField (Label value) = value  -- | Fetch a value from a record, like 'getField', but also keep it wrapped by its label.-getLabel :: forall label record a. HasField label record a => record -> Label label a+getLabel :: forall label record a. (HasField label record a) => record -> Label label a getLabel rec = rec & getField @label & label @label  -- | 'fmap' over the contents of the labbelled value. Helper.@@ -99,7 +102,7 @@ mapLabel f (Label a) = Label @label $ f a  -- | 'traverse' over the contents of the labbelled value. Helper.-traverseLabel :: forall label f a b. Functor f => (a -> f b) -> Label label a -> f (Label label b)+traverseLabel :: forall label f a b. (Functor f) => (a -> f b) -> Label label a -> f (Label label b) traverseLabel fab (Label a) = Label @label <$> fab a  -- | A named 2-element tuple. Since the elements are named, you can access them with `.`.@@ -153,7 +156,7 @@ -- otherwise it cannot infer it. focusOnField ::   forall field rec subrec t.-  HasField field subrec t =>+  (HasField field subrec t) =>   (rec -> subrec) ->   rec ->   T2 field t "dat" rec@@ -169,6 +172,29 @@ tupleToT2 :: forall l1 l2 t1 t2. (t1, t2) -> T2 l1 t1 l2 t2 tupleToT2 (t1, t2) = T2 (label @l1 t1) (label @l2 t2) +-- | If you have a tuple of lists, make it into a list of tuples. The names are attached to each value.+zipT2 ::+  forall l1 l2 t1 t2.+  ( HasField l1 (T2 l1 [t1] l2 [t2]) [t1],+    HasField l2 (T2 l1 [t1] l2 [t2]) [t2]+  ) =>+  T2 l1 [t1] l2 [t2] ->+  [T2 l1 t1 l2 t2]+zipT2 xs =+  zipWith+    (\t1 t2 -> T2 (label @l1 t1) (label @l2 t2))+    (getField @l1 xs)+    (getField @l2 xs)++-- | If you have a list of tuples, make it into a tuple of lists. The names are attached to each value.+unzipT2 :: forall l1 t1 l2 t2. [T2 l1 t1 l2 t2] -> T2 l1 [t1] l2 [t2]+unzipT2 xs = xs <&> toTup & unzip & fromTup+  where+    toTup :: forall a b. T2 a t1 b t2 -> (t1, t2)+    toTup (T2 a b) = (getField @a a, getField @b b)+    fromTup :: (a, b) -> T2 l1 a l2 b+    fromTup (t1, t2) = T2 (label @l1 t1) (label @l2 t2)+ -- | A named 3-element tuple. Since the elements are named, you can access them with `.`. See 'T2' for an example. data T3 (l1 :: Symbol) t1 (l2 :: Symbol) t2 (l3 :: Symbol) t3 = T3 (Label l1 t1) (Label l2 t2) (Label l3 t3)   deriving stock (Show, Eq, Ord)@@ -201,6 +227,31 @@ tupleToT3 :: forall l1 l2 l3 t1 t2 t3. (t1, t2, t3) -> T3 l1 t1 l2 t2 l3 t3 tupleToT3 (t1, t2, t3) = T3 (label @l1 t1) (label @l2 t2) (label @l3 t3) +-- | If you have a tuple of lists, make it into a list of tuples. The names are attached to each value.+zipT3 ::+  forall l1 l2 t1 t2 l3 t3.+  ( HasField l1 (T3 l1 [t1] l2 [t2] l3 [t3]) [t1],+    HasField l2 (T3 l1 [t1] l2 [t2] l3 [t3]) [t2],+    HasField l3 (T3 l1 [t1] l2 [t2] l3 [t3]) [t3]+  ) =>+  T3 l1 [t1] l2 [t2] l3 [t3] ->+  [T3 l1 t1 l2 t2 l3 t3]+zipT3 xs =+  zipWith3+    (\t1 t2 t3 -> T3 (label @l1 t1) (label @l2 t2) (label @l3 t3))+    (getField @l1 xs)+    (getField @l2 xs)+    (getField @l3 xs)++-- | If you have a list of tuples, make it into a tuple of lists. The names are attached to each value.+unzipT3 :: forall l1 t1 l2 t2 l3 t3. [T3 l1 t1 l2 t2 l3 t3] -> T3 l1 [t1] l2 [t2] l3 [t3]+unzipT3 xs = xs <&> toTup & unzip3 & fromTup+  where+    toTup :: forall a b c. T3 a t1 b t2 c t3 -> (t1, t2, t3)+    toTup (T3 a b c) = (getField @a a, getField @b b, getField @c c)+    fromTup :: (a, b, c) -> T3 l1 a l2 b l3 c+    fromTup (t1, t2, t3) = T3 (label @l1 t1) (label @l2 t2) (label @l3 t3)+ -- | A named 2-alternative sum (“'Either' with labels”). data E2 (l1 :: Symbol) t1 (l2 :: Symbol) t2   = E21 (Label l1 t1)@@ -259,7 +310,7 @@     & (\(t1s, t2s) -> T2 (label @l1 t1s) (label @l2 t2s))  -- | Map a monadic (actually just a functor-ic) function over each possibility in this enum. All fields have to have the same type.-monoTraverseE2 :: Functor f => (t -> f t') -> E2 l1 t l2 t -> f (E2 l1 t' l2 t')+monoTraverseE2 :: (Functor f) => (t -> f t') -> E2 l1 t l2 t -> f (E2 l1 t' l2 t') monoTraverseE2 f = \case   E21 lbl -> lbl & traverseLabel f <&> E21   E22 lbl -> lbl & traverseLabel f <&> E22