diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -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)
 
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -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
 
diff --git a/docs/license-report.md b/docs/license-report.md
--- a/docs/license-report.md
+++ b/docs/license-report.md
@@ -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` |
diff --git a/duoids.cabal b/duoids.cabal
--- a/duoids.cabal
+++ b/duoids.cabal
@@ -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
diff --git a/src/Control/Duoidal.hs b/src/Control/Duoidal.hs
--- a/src/Control/Duoidal.hs
+++ b/src/Control/Duoidal.hs
@@ -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)
