packages feed

duoids 0.0.1.0 → 0.1.0.0

raw patch · 6 files changed

+464/−43 lines, 6 filesdep ~doctestdep ~no-recursionsetup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: doctest, no-recursion

API changes (from Hackage documentation)

- Control.Duoidal: instance GHC.Base.Applicative f => GHC.Base.Applicative (Control.Duoidal.Parallel (Control.Duoidal.Commutative f))
- Control.Duoidal: instance GHC.Base.Applicative f => GHC.Base.Applicative (Control.Duoidal.Sequential (Control.Duoidal.Commutative f))
+ Control.Duoidal: commutativeAp :: forall (f :: Type -> Type) a b. Monad f => Parallel f (a -> b) -> Parallel f a -> Parallel f b
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b) => GHC.Base.Applicative (Control.Duoidal.Parallel ((,,) a b))
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b) => GHC.Base.Applicative (Control.Duoidal.Sequential ((,,) a b))
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b) => GHC.Base.Monad (Control.Duoidal.Sequential ((,,) a b))
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b, Data.Duoid.Duoid c) => GHC.Base.Applicative (Control.Duoidal.Parallel ((,,,) a b c))
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b, Data.Duoid.Duoid c) => GHC.Base.Applicative (Control.Duoidal.Sequential ((,,,) a b c))
+ Control.Duoidal: instance (Data.Duoid.Duoid a, Data.Duoid.Duoid b, Data.Duoid.Duoid c) => GHC.Base.Monad (Control.Duoidal.Sequential ((,,,) a b c))
+ Control.Duoidal: instance (Data.Duoid.Normal a, Data.Duoid.Normal b) => Control.Duoidal.Normal ((,,) a b)
+ Control.Duoidal: instance (Data.Duoid.Normal a, Data.Duoid.Normal b, Data.Duoid.Normal c) => Control.Duoidal.Normal ((,,,) a b c)
+ Control.Duoidal: instance Control.Duoidal.Normal ((->) r)
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Complex.Complex
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Functor.Identity.Identity
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Monoid.First
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Monoid.Last
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Ord.Down
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Proxy.Proxy
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.First
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Internal.Dual
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Internal.Product
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Internal.Sum
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Last
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Max
+ Control.Duoidal: instance Control.Duoidal.Normal Data.Semigroup.Min
+ Control.Duoidal: instance Control.Duoidal.Normal GHC.Maybe.Maybe
+ Control.Duoidal: instance Control.Duoidal.Normal GHC.Tuple.Prim.Solo
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel ((->) r))
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Complex.Complex)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Functor.Identity.Identity)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Monoid.First)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Monoid.Last)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Ord.Down)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Proxy.Proxy)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.First)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Internal.Dual)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Internal.Product)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Internal.Sum)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Last)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Max)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel Data.Semigroup.Min)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel GHC.Maybe.Maybe)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Parallel GHC.Tuple.Prim.Solo)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential ((->) r))
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Complex.Complex)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Functor.Identity.Identity)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Monoid.First)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Monoid.Last)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Ord.Down)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Proxy.Proxy)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.First)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Internal.Dual)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Internal.Product)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Internal.Sum)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Last)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Max)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential Data.Semigroup.Min)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential GHC.Maybe.Maybe)
+ Control.Duoidal: instance GHC.Base.Applicative (Control.Duoidal.Sequential GHC.Tuple.Prim.Solo)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential ((->) r))
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Complex.Complex)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Functor.Identity.Identity)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Monoid.First)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Monoid.Last)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Ord.Down)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Proxy.Proxy)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.First)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Internal.Dual)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Internal.Product)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Internal.Sum)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Last)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Max)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential Data.Semigroup.Min)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential GHC.Maybe.Maybe)
+ Control.Duoidal: instance GHC.Base.Monad (Control.Duoidal.Sequential GHC.Tuple.Prim.Solo)
+ Control.Duoidal: instance GHC.Base.Monad f => Control.Duoidal.Normal (Control.Duoidal.Commutative f)
+ Control.Duoidal: instance GHC.Base.Monad f => GHC.Base.Applicative (Control.Duoidal.Commutative f)
+ Control.Duoidal: instance GHC.Base.Monad f => GHC.Base.Applicative (Control.Duoidal.Parallel (Control.Duoidal.Commutative f))
+ Control.Duoidal: instance GHC.Base.Monad f => GHC.Base.Applicative (Control.Duoidal.Sequential (Control.Duoidal.Commutative f))
+ Control.Duoidal: instance GHC.Base.Monad f => GHC.Base.Monad (Control.Duoidal.Commutative f)
+ Control.Duoidal: instance GHC.Base.Monoid a => GHC.Base.Applicative (Control.Duoidal.Parallel (Data.Functor.Const.Const a))
+ Control.Duoidal: instance GHC.Base.Monoid a => GHC.Base.Applicative (Control.Duoidal.Sequential (Data.Functor.Const.Const a))
+ Control.Duoidal: instance GHC.Base.Monoid a => GHC.Base.Monad (Control.Duoidal.Sequential (Data.Functor.Const.Const a))
+ Control.Duoidal: sequentialAp :: forall (f :: Type -> Type) a b. Monad f => Sequential f (a -> b) -> Sequential f a -> Sequential f b

Files

CHANGELOG.md view
@@ -5,10 +5,46 @@ The format is based on [Keep a Changelog 1.1](https://keepachangelog.com/en/1.1.0/), and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). -## [0.0.1.0] -+## [0.1.0.0] - 2026-08-04  ### Added +- `Applicative` and `Monad` instances for `Commutative` itself, so it can be+  used with `DerivingVia` to give your own commutative `Monad` a `Duoidal`+  instance, rather than only being usable through `Parallel` and `Sequential`+- `commutativeAp` and `sequentialAp`+- `Normal` duoidal instances for the commutative functors in base: `Complex`,+  `Down`, `Dual`, `Identity`, `Max`, `Maybe`, `Min`, `Monoid.First`,+  `Monoid.Last`, `Monoid.Product`, `Proxy`, `Semigroup.First`, `Semigroup.Last`,+  `Solo`, `Sum`, `->`, `(,,)`, `(,,,)`, and `Const`+- Cabal flag `lint`, which (when disabled, as is the default) allows the+  dependency graph to be pruned, potentially avoiding solver & compilation+  issues.++### Changed++- `Applicative (Parallel (Commutative f))` and `Applicative (Sequential+  (Commutative f))` now require `f` to be a `Monad` rather than merely an+  `Applicative`. `Commutative` was always documented as being for commutative+  `Monad`s, but the instances asked for less than they meant; the new+  `Commutative` instances need the stronger constraint.++### Deprecated++- `sequentialLiftA2` — use `sequentialAp` instead++### Fixed++- `no-recursion` is no longer a dependency by default (thanks to the+  aforementioned `lint` change).++## [0.0.1.0] - 2025-11-17++### Added+ - initial release of this package -[0.0.1.0]: https://github.com/sellout/duoids/releases/tag/v0.0.1.0+<!-- NB: The version on the left is the Haskell package version (PVP), the version on the right is the repo (tag) version (SemVer). Their only relationship is that a change of any severity on the left implies a change of at least that severity on the right. -->++[0.1.0.0]: https://github.com/sellout/duoids/compare/v0.1.0...v1.0.0+[0.0.1.0]: https://github.com/sellout/duoids/releases/tag/v0.1.0
README.md view
@@ -107,11 +107,15 @@  ### [either](https://hackage.haskell.org/package/either) -The `either` package has a `Validation` type that’s isomorphic to `Either` and has an applicative instance that’s the same as the `Parallel (Either e)` instance here. However, it doesn’t have anything like the `Duoidal` class, and so requires manual conversion back and forth between `Either` and `Validation`.+The `either` package has a `Validation` type that’s isomorphic to `Either` and has an `Applicative` instance that’s the same as the `Parallel (Either e)` instance here. However, it doesn’t have anything like the `Duoidal` class, and so requires manual conversion back and forth between `Either` and `Validation`.  ### [Haskerwaul](https://github.com/sellout/haskerwaul#readme)  A broader package that contains a more general (category polymorphic) implementation of duoids. It’s also much less pragmatic.++### [multi-except](https://hackage.haskell.org/package/multi-except)++This seems like another approach to `Validation`, but I haven’t used it.  ### [United Monoids](https://github.com/snowleopard/united) 
Setup.hs view
@@ -7,7 +7,6 @@ -- Warns even when `Unsafe` is explicit, not inferred. See -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689 {-# OPTIONS_GHC -Wno-unsafe #-}-{-# OPTIONS_GHC -fplugin=NoRecursion #-}  module Main (main) where 
docs/license-report.md view
@@ -9,7 +9,7 @@ | Name | Version | [SPDX](https://spdx.org/licenses/) License Id | Description | Also depended upon by | | --- | --- | --- | --- | --- | | **`base`** | [`4.20.0.0`](http://hackage.haskell.org/package/base-4.20.0.0) | [`BSD-3-Clause`](http://hackage.haskell.org/package/base-4.20.0.0/src/LICENSE) | Core data structures and operations | *(core library)* |-| `no-recursion` | [`0.3.0.0`](http://hackage.haskell.org/package/no-recursion-0.3.0.0) | [`(AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR AGPL-3.0-only OR LicenseRef-commercial)`](http://hackage.haskell.org/package/no-recursion-0.3.0.0/src/LICENSE) | A GHC plugin to remove support for recursion |  |+| `no-recursion` | [`0.4.0.1`](http://hackage.haskell.org/package/no-recursion-0.4.0.1) | [`(AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR LicenseRef-proprietary)`](http://hackage.haskell.org/package/no-recursion-0.4.0.1/src/LICENSE) | A GHC plugin to remove support for recursion |  |  ## Indirect transitive dependencies @@ -23,10 +23,11 @@ | **`directory`** | [`1.3.8.3`](http://hackage.haskell.org/package/directory-1.3.8.3) | [`BSD-3-Clause`](http://hackage.haskell.org/package/directory-1.3.8.3/src/LICENSE) | Platform-agnostic library for filesystem operations | `ghc`, `ghc-boot`, `hpc`, `process` | | **`exceptions`** | [`0.10.7`](http://hackage.haskell.org/package/exceptions-0.10.7) | [`BSD-3-Clause`](http://hackage.haskell.org/package/exceptions-0.10.7/src/LICENSE) | Extensible optionally-pure exceptions | `filepath`, `ghc`, `os-string`, `semaphore-compat` | | **`filepath`** | [`1.5.2.0`](http://hackage.haskell.org/package/filepath-1.5.2.0) | [`BSD-3-Clause`](http://hackage.haskell.org/package/filepath-1.5.2.0/src/LICENSE) | Library for manipulating FilePaths in a cross platform way. | `directory`, `ghc`, `ghc-boot`, `ghci`, `hpc`, `process`, `unix` |-| **`ghc`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-9.10.1/src/LICENSE) | The GHC API | `no-recursion` |+| **`ghc`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-9.10.1/src/LICENSE) | The GHC API | `ghc-compat-plugin`, `no-recursion` | | **`ghc-bignum`** | [`1.3`](http://hackage.haskell.org/package/ghc-bignum-1.3) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-bignum-1.3/src/LICENSE) | GHC BigNum library | `ghc-internal` | | **`ghc-boot`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-boot-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-boot-9.10.1/src/LICENSE) | Shared functionality between GHC and its boot libraries | `ghc`, `ghci` |-| **`ghc-boot-th`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-boot-th-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-boot-th-9.10.1/src/LICENSE) | Shared functionality between GHC and the @template-haskell@ library | `ghc-boot`, `template-haskell` |+| **`ghc-boot-th`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-boot-th-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-boot-th-9.10.1/src/LICENSE) | Shared functionality between GHC and the @template-haskell@ library | `ghc-boot`, `ghc-compat-plugin`, `template-haskell` |+| `ghc-compat-plugin` | [`0.1.0.1`](http://hackage.haskell.org/package/ghc-compat-plugin-0.1.0.1) | [`AGPL-3.0-only`](http://hackage.haskell.org/package/ghc-compat-plugin-0.1.0.1/src/LICENSE.AGPL-3.0-only) | Eases support for multiple GHC versions | `no-recursion` | | **`ghc-heap`** | [`9.10.1`](http://hackage.haskell.org/package/ghc-heap-9.10.1) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-heap-9.10.1/src/LICENSE) | Functions for walking GHC's heap | `ghc`, `ghci` | | **`ghc-internal`** | [`9.1001.0`](http://hackage.haskell.org/package/ghc-internal-9.1001.0) | [`BSD-3-Clause`](http://hackage.haskell.org/package/ghc-internal-9.1001.0/src/LICENSE) | Basic libraries | `base`, `ghc-heap` | | **`ghc-platform`** | [`0.1.0.0`](http://hackage.haskell.org/package/ghc-platform-0.1.0.0) |  *MISSING* | *MISSING* | `ghc-boot` |
duoids.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: duoids-version: 0.0.1.0+version: 0.1.0.0 synopsis: Unifying parallel and sequential operations description: Duoids relate a pair of monoids, where one can be seen as             “parallel” and the other “sequential”.@@ -38,17 +38,6 @@   location: https://github.com/sellout/duoids.git   subdir: core -flag noisy-deprecations-  description:-    Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms-    and types. Consenquently, you can get spurious warnings when there’s a name-    collision and the name in the other namespace is deprecated. Or you can-    choose to not get those warnings, at the risk of not being warned when-    there’s a name collision and the namespace you’re referencing is the one-    that’s deprecated.-  default: True-  manual: False- custom-setup   setup-depends:     -- TODO: Due to haskell/cabal#3751, `Cabal` has to be specified even though@@ -59,8 +48,27 @@     Cabal >= 3.0 && < 99,     base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0},     cabal-doctest ^>= {1.0.0},-    no-recursion ^>= {0.2.0, 0.3.0}, +flag noisy-deprecations+  description:+    Prior to GHC 9.10, the @DEPRECATED@ pragma can’t distinguish between terms+    and types. Consenquently, you can get spurious warnings when there’s a name+    collision and the name in the other namespace is deprecated. Or you can+    choose to not get those warnings, at the risk of not being warned when+    there’s a name collision and the namespace you’re referencing is the one+    that’s deprecated.+  default: True+  -- Because disabling this flag won’t help the solver.+  manual: True++flag lint+  description:+    Compile with "NoRecursion" enabled. This is intended for developers of this+    package.+  default: False+  -- Because disabling this flag won’t help the solver.+  manual: True+ -- This mimics the GHC2024 extension -- (https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html?highlight=doandifthenelse#extension-GHC2024), -- but supporting compilers back to GHC 8.0. If the oldest supported compiler@@ -84,7 +92,6 @@   import: GHC2024   build-depends:     base ^>= {4.18.0, 4.19.0, 4.20.0, 4.21.0},-    no-recursion ^>= {0.2.0, 0.3.0},   ghc-options:     -Weverything     -- This one just reports unfixable things, AFAICT.@@ -94,7 +101,6 @@     -- Warns even when `Unsafe` is explicit, not inferred. See     -- https://gitlab.haskell.org/ghc/ghc/-/issues/16689     -Wno-unsafe-    -fplugin=NoRecursion   if impl(ghc >= 9.8.1)     ghc-options:       -- Inference good.@@ -121,11 +127,18 @@     NoStarIsType     NoTypeApplications   if flag(noisy-deprecations)-    cpp-options: -DSELLOUT_NOISY_DEPRECATIONS+    cpp-options:+      -DSELLOUT_NOISY_DEPRECATIONS+  if flag(lint)+    build-depends:+      no-recursion ^>= {0.2.0, 0.3.0, 0.4.0},+    ghc-options:+      -fplugin=NoRecursion  library   import: defaults-  hs-source-dirs: src+  hs-source-dirs:+    src   exposed-modules:     Control.Duoidal     Control.Duoidal.Either@@ -141,7 +154,7 @@   hs-source-dirs: tests   main-is: doctests.hs   build-depends:-    doctest ^>= {0.21.1, 0.22.6, 0.24.0},+    doctest ^>= {0.21.1, 0.22.6, 0.24.0, 0.25.0},     duoids,   -- TODO: The sections below here are necessary because we don’t have control   --       over the generated `Build_doctests.hs` file. So we have to silence
src/Control/Duoidal.hs view
@@ -141,16 +141,24 @@      -- * instance helpers     normalPure,+    sequentialAp,     sequentialBind,     sequentialLiftA2,     sequentialPure,      -- * duoids from commutative `Monad`s     Commutative (Commutative, getCommutative),+    commutativeAp,   ) where -import "base" Control.Applicative (Alternative, Applicative, empty, (<|>))+import "base" Control.Applicative+  ( Alternative,+    Applicative,+    Const (Const),+    empty,+    (<|>),+  ) import "base" Control.Applicative qualified as Base   ( liftA2,     liftA3,@@ -163,7 +171,8 @@ import "base" Control.Category ((.)) import "base" Control.Monad (Monad) import "base" Control.Monad qualified as Base-  ( forever,+  ( ap,+    forever,     join,     liftM2,     return,@@ -182,18 +191,25 @@     bitraverse,   ) import "base" Data.Bool (Bool)+import "base" Data.Complex (Complex) import "base" Data.Either (Either (Left, Right), either) import "base" Data.Eq (Eq) import "base" Data.Foldable (Foldable) import "base" Data.Foldable qualified as Base (for_, traverse_) import "base" Data.Function (const, ($)) import "base" Data.Functor (Functor, fmap)+import "base" Data.Functor.Identity (Identity) import "base" Data.Kind (Constraint, Type)-import "base" Data.Monoid (Monoid, mempty)-import "base" Data.Ord (Ord)-import "base" Data.Semigroup (Semigroup, (<>))+import "base" Data.Maybe (Maybe)+import "base" Data.Monoid (Dual, Monoid, Sum, mempty)+import "base" Data.Monoid qualified as Monoid+import "base" Data.Ord (Down, Ord)+import "base" Data.Proxy (Proxy)+import "base" Data.Semigroup (Max, Min, Semigroup, (<>))+import "base" Data.Semigroup qualified as Semigroup import "base" Data.Traversable (Traversable) import "base" Data.Traversable qualified as Base (for, traverse)+import "base" Data.Tuple (Solo) import "base" GHC.TypeError (ErrorMessage (Text), TypeError) import "base" System.IO (IO) import "base" Text.Read (Read)@@ -467,7 +483,12 @@   Sequential f b ->   Sequential f c sequentialLiftA2 f (Sequential a) = Sequential . Base.liftA2 f a . getSequential+{-# DEPRECATED sequentialLiftA2 "use ‘sequentialAp’ instead" #-} +sequentialAp ::+  (Monad f) => Sequential f (a -> b) -> Sequential f a -> Sequential f b+sequentialAp (Sequential f) = Sequential . Base.ap f . getSequential+ sequentialBind ::   (Monad f) => Sequential f a -> (a -> Sequential f b) -> Sequential f b sequentialBind (Sequential a) f = Sequential $ a Base.>>= (getSequential . f)@@ -476,25 +497,329 @@  -- | Commutative `Monad`s form a duoid with themselves. -----  __NB__: Don’t use this newtype on a non-commutative Monad.+--   You can use this with @DerivingVia@ to create instances for your own+--   commutative `Monad`s.+--+--   For existing types, instances for types in base should be available here,+--   but those for other packages may not exist. For those that don’t, you can+--+-- 1. wrap the type in `Commutative` when you need the instance,+-- 2. define orphan instances that look like the instances for `Commutative`, or+-- 3. use the provided operations (like `commutativeAp`) directly.+--+--   Some examples of commutative monads:+-- - those isomorphic to `Identity` (many newtypes fall into this bucket)+-- - reader (@->@)+-- - `Maybe`+-- - `Proxy`+--+--   You can also wrap types that already have `Duoidal` instances in+--   `Commutative` as well (as long as they have an unwrapped `Monad` instance).+--   If their existing `Duoidal` instance isn’t the commutative one, the+--   `Commutative` wrapper will give you the commutative one. I don’t know if+--   this one is correct, but if you have a commutative writer (say, @`Writer`+--   (`Set` `Char`)@), wrapping it in `Commutative` would give you a `Duoidal`+--   instance that behaves commutatively. However, @`Set` a@ should already have+--   a commutative `Duoid` instance, so I don’t think it actually buys you+--   anything.+--+--  __NB__: Don’t use this newtype to turn a non-commutative `Monad` into a+--          duoid. type Commutative :: forall {k}. (k -> Type) -> k -> Type newtype Commutative f a = Commutative {getCommutative :: f a}   deriving stock (Eq, Ord, Read, Show, Functor, Foldable, Traversable) -instance (Applicative f) => Applicative (Parallel (Commutative f)) where-  pure = Parallel . Commutative . Base.pure-  liftA2 f (Parallel (Commutative a)) (Parallel (Commutative b)) =-    Parallel . Commutative $ Base.liftA2 f a b+instance (Monad f) => Applicative (Commutative f) where+  pure = Commutative . Base.return+  Commutative f <*> Commutative a = Commutative $ Base.ap f a -instance (Applicative f) => Applicative (Sequential (Commutative f)) where-  pure = Sequential . Commutative . Base.pure-  liftA2 f (Sequential (Commutative a)) (Sequential (Commutative b)) =-    Sequential . Commutative $ Base.liftA2 f a b+instance (Monad f) => Monad (Commutative f) where+  Commutative a >>= f = Commutative $ a Base.>>= (getCommutative . f) +commutativeAp ::+  (Monad f) =>+  Parallel f (a -> b) ->+  Parallel f a ->+  Parallel f b+commutativeAp (Parallel f) = Parallel . Base.ap f . getParallel++instance (Monad f) => Applicative (Parallel (Commutative f)) where+  pure = normalPure+  (<*>) = commutativeAp++instance (Monad f) => Applicative (Sequential (Commutative f)) where+  pure = sequentialPure+  (<*>) = sequentialAp+ instance (Monad f) => Monad (Sequential (Commutative f)) where-  Sequential (Commutative a) >>= f =-    Sequential . Commutative $ a Base.>>= (getCommutative . getSequential . f)+  (>>=) = sequentialBind +instance (Monad f) => Normal (Commutative f)++-- `Complex` is a commutative duoidal functor++instance Applicative (Parallel Complex) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Complex) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Complex) where+  (>>=) = sequentialBind++instance Normal Complex++-- `Down` is a commutative duoidal functor++instance Applicative (Parallel Down) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Down) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Down) where+  (>>=) = sequentialBind++instance Normal Down++-- `Dual` is a commutative duoidal functor++instance Applicative (Parallel Dual) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Dual) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Dual) where+  (>>=) = sequentialBind++instance Normal Dual++-- `Monoid.First` is a commutative duoidal functor++instance Applicative (Parallel Monoid.First) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Monoid.First) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Monoid.First) where+  (>>=) = sequentialBind++instance Normal Monoid.First++-- `Semigroup.First` is a commutative duoidal functor++instance Applicative (Parallel Semigroup.First) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Semigroup.First) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Semigroup.First) where+  (>>=) = sequentialBind++instance Normal Semigroup.First++-- `Identity` is a commutative duoidal functor++instance Applicative (Parallel Identity) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Identity) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Identity) where+  (>>=) = sequentialBind++instance Normal Identity++-- `Monoid.Last` is a commutative duoidal functor++instance Applicative (Parallel Monoid.Last) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Monoid.Last) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Monoid.Last) where+  (>>=) = sequentialBind++instance Normal Monoid.Last++-- `Semigroup.Last` is a commutative duoidal functor++instance Applicative (Parallel Semigroup.Last) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Semigroup.Last) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Semigroup.Last) where+  (>>=) = sequentialBind++instance Normal Semigroup.Last++-- `Max` is a commutative duoidal functor++instance Applicative (Parallel Max) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Max) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Max) where+  (>>=) = sequentialBind++instance Normal Max++-- `Maybe` is a commutative duoidal functor++instance Applicative (Parallel Maybe) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Maybe) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Maybe) where+  (>>=) = sequentialBind++instance Normal Maybe++-- `Min` is a commutative duoidal functor++instance Applicative (Parallel Min) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Min) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Min) where+  (>>=) = sequentialBind++instance Normal Min++-- `Monoid.Product` is a commutative duoidal functor++instance Applicative (Parallel Monoid.Product) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Monoid.Product) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Monoid.Product) where+  (>>=) = sequentialBind++instance Normal Monoid.Product++-- `Proxy` is a commutative duoidal functor++instance Applicative (Parallel Proxy) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Proxy) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Proxy) where+  (>>=) = sequentialBind++instance Normal Proxy++-- `Solo` is a commutative duoidal functor++instance Applicative (Parallel Solo) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Solo) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Solo) where+  (>>=) = sequentialBind++instance Normal Solo++-- `Sum` is a commutative duoidal functor++instance Applicative (Parallel Sum) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential Sum) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential Sum) where+  (>>=) = sequentialBind++instance Normal Sum++-- reader is a commutative duoidal functor++instance Applicative (Parallel ((->) r)) where+  pure = normalPure+  (<*>) = commutativeAp++instance Applicative (Sequential ((->) r)) where+  pure = sequentialPure+  (<*>) = sequentialAp++instance Monad (Sequential ((->) r)) where+  (>>=) = sequentialBind++instance Normal ((->) r)++-- Const++instance (Monoid a) => Applicative (Parallel (Const a)) where+  pure = normalPure+  liftA2 f (Parallel a) (Parallel b) = Parallel $ liftA2 f a b++instance (Monoid a) => Applicative (Sequential (Const a)) where+  pure = Sequential . pure+  liftA2 f (Sequential a) = Sequential . Base.liftA2 f a . getSequential++-- | The `Const` duoidal functor provides an illustration of why we need to have+--   both `Parallel` and `Sequential` newtypes – relying on the underlying+--   `Applicative` (and only having the `Sequential` newtype) would mean that+--   any duoidal structure would only have a `Monad` available under+--   `Sequential`, which would be a prettty serious impact. On the other hand,+--   relying on the underlying `Monad` (and only having the `Parallel` newtype)+--   is much more natural, but `Const`, for example, having a `Monad` instance+--   would make it basically useless, and the more interesting `Applicative`+--   instance would only be available under the `Parallel` netwype. The current+--   structure allows either the `Applicative` or `Monad` instance to be the one+--   exposed directly.+instance (Monoid a) => Monad (Sequential (Const a)) where+  Sequential (Const a) >>= _ = Sequential $ Const a+ -- Either  instance (Semigroup e) => Applicative (Parallel (Either e)) where@@ -509,7 +834,7 @@  instance (Semigroup e) => Applicative (Sequential (Either e)) where   pure = sequentialPure-  liftA2 = sequentialLiftA2+  (<*>) = sequentialAp  instance (Semigroup e) => Monad (Sequential (Either e)) where   (>>=) = sequentialBind@@ -539,7 +864,7 @@  instance Applicative (Sequential IO) where   pure = sequentialPure-  liftA2 = sequentialLiftA2+  (<*>) = sequentialAp  instance Monad (Sequential IO) where   (>>=) = sequentialBind@@ -584,3 +909,46 @@ -- | A writer is a `Normal` `Duoidal` functor when the writee is a --   `Duoid.Normal` `Duoid`. instance (Duoid.Normal a) => Normal ((,) a)++instance (Duoid a, Duoid b) => Applicative (Parallel ((,,) a b)) where+  pure = Parallel . (pempty,pempty,)+  liftA2 f (Parallel (a, b, x)) (Parallel (a', b', y)) =+    Parallel (a |-| a', b |-| b', f x y)++instance (Duoid a, Duoid b) => Applicative (Sequential ((,,) a b)) where+  pure = Sequential . (sempty,sempty,)+  liftA2 = Base.liftM2++instance (Duoid a, Duoid b) => Monad (Sequential ((,,) a b)) where+  Sequential (u, v, a) >>= k =+    case k a of Sequential (u', v', b) -> Sequential (u >-> u', v >-> v', b)++-- | A writer is a `Normal` `Duoidal` functor when the writee is a+--   `Duoid.Normal` `Duoid`.+instance (Duoid.Normal a, Duoid.Normal b) => Normal ((,,) a b)++instance+  (Duoid a, Duoid b, Duoid c) =>+  Applicative (Parallel ((,,,) a b c))+  where+  pure = Parallel . (pempty,pempty,pempty,)+  liftA2 f (Parallel (a, b, c, x)) (Parallel (a', b', c', y)) =+    Parallel (a |-| a', b |-| b', c |-| c', f x y)++instance+  (Duoid a, Duoid b, Duoid c) =>+  Applicative (Sequential ((,,,) a b c))+  where+  pure = Sequential . (sempty,sempty,sempty,)+  liftA2 = Base.liftM2++instance (Duoid a, Duoid b, Duoid c) => Monad (Sequential ((,,,) a b c)) where+  Sequential (u, v, w, a) >>= k =+    case k a of+      Sequential (u', v', w', b) -> Sequential (u >-> u', v >-> v', w >-> w', b)++-- | A writer is a `Normal` `Duoidal` functor when the writee is a+--   `Duoid.Normal` `Duoid`.+instance+  (Duoid.Normal a, Duoid.Normal b, Duoid.Normal c) =>+  Normal ((,,,) a b c)