From 7abcad2410912f7a625866cc5c866f4606a95483 Mon Sep 17 00:00:00 2001
From: gusty <1261319+gusty@users.noreply.github.com>
Date: Thu, 8 Jan 2026 16:34:14 +0100
Subject: [PATCH 1/4] Add 2 layer forward applicative variations
---
src/FSharpPlus/Operators.fs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/src/FSharpPlus/Operators.fs b/src/FSharpPlus/Operators.fs
index 44130d98f..3b241069b 100644
--- a/src/FSharpPlus/Operators.fs
+++ b/src/FSharpPlus/Operators.fs
@@ -270,6 +270,29 @@ module Operators =
/// Applicative
let inline (<.) (x: '``ZipApplicative<'U>``) (y: '``ZipApplicative<'T>``) : '``ZipApplicative<'U>`` = ((fun (k: 'U) (_: 'T) -> k ) x : '``ZipApplicative<'T->'U>``) <.> y
+ ///
+ /// Sequences two nested applicatives left-to-right, discarding the value of the first argument.
+ ///
+ /// Applicative
+ let inline ( **>) (x: '``Applicative1>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( *>) x) <*> y
+
+ ///
+ /// Applies two nested applicatives left-to-right, discarding the value of the first argument.
+ /// The outer applicative is non-sequential (zip-like), while the inner one is sequential.
+ ///
+ let inline ( .*>) (x: '``ZipApplicative>``) (y: '``ZipApplicative>``) : '``ZipApplicative1>`` = (Map.Invoke ( *>) x) <.> y
+
+ ///
+ /// Applies two nested applicatives left-to-right, discarding the value of the first argument.
+ /// The outer applicative is sequential, while the inner one is non-sequential (zip-like).
+ ///
+ let inline ( *.>) (x: '``Applicative>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( .>) x) <*> y
+
+ ///
+ /// Applies two nested applicatives left-to-right in a non-sequential way, discarding the value of the first argument.
+ ///
+ let inline ( ..>) (x: '``ZipApplicative1>``) (y: '``ZipApplicative1>``) : '``ZipApplicative1>`` = (Map.Invoke ( .>) x) <.> y
+
///
/// Applies 2 lifted arguments to a non-lifted function with pointwise and/or parallel semantics.
/// Operator version of 'map2'.
From 96b41ef3425190e3117a3ea0c331983f8d43061b Mon Sep 17 00:00:00 2001
From: gusty <1261319+gusty@users.noreply.github.com>
Date: Thu, 8 Jan 2026 18:23:26 +0100
Subject: [PATCH 2/4] Add forward/backward zip-applicatives to Compose
---
src/FSharpPlus/Data/Compose.fs | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/FSharpPlus/Data/Compose.fs b/src/FSharpPlus/Data/Compose.fs
index b05eb4f21..0423178a7 100644
--- a/src/FSharpPlus/Data/Compose.fs
+++ b/src/FSharpPlus/Data/Compose.fs
@@ -56,6 +56,20 @@ type Compose<'``functorF<'functorG<'t>>``> = Compose of '``functorF<'functorG<'t
static member inline (<.>) (Compose (f: '``ApplicativeF<'ApplicativeG<'T -> 'U>``), Compose (x: '``ApplicativeF<'ApplicativeG<'T>``)) =
Compose ((((<.>) : '``ApplicativeG<'T -> 'U>`` -> '``ApplicativeG<'T>`` -> '``ApplicativeG<'U>``) f: '``ApplicativeF<'ApplicativeG<'T> -> 'ApplicativeG<'U>`` ) <.> x: '``ApplicativeF<'ApplicativeG<'U>``)
+ ///
+ /// Applies two composed applicatives left-to-right in a non-sequential way, discarding the value of the first argument.
+ ///
+ /// Applicative
+ static member inline ( .>) (Compose (x: '``FunctorF<'FunctorG<'T>>``), Compose (y: '``FunctorF<'FunctorG<'U>>``)) : Compose<'``FunctorF<'FunctorG<'U>>``> =
+ (ZipApply.Invoke << Map.Invoke (ZipApply.Invoke << Map.Invoke (fun _ k -> k))) x y |> Compose
+
+ ///
+ /// Applies two composed applicatives left-to-right in a non-sequential way, discarding the value of the second argument.
+ ///
+ /// Applicative
+ static member inline (<. ) (Compose (x: '``FunctorF<'FunctorG<'U>>``), Compose (y: '``FunctorF<'FunctorG<'T>>``)) : Compose<'``FunctorF<'FunctorG<'U>>``> =
+ (ZipApply.Invoke << Map.Invoke (ZipApply.Invoke << Map.Invoke (fun k _ -> k))) x y |> Compose
+
static member inline Map2 (f: 'T -> 'U -> 'V, Compose (x: '``ApplicativeF<'ApplicativeG<'T>``), Compose (y: '``ApplicativeF<'ApplicativeG<'U>``)) =
Compose (Map2.Invoke (Map2.Invoke f: '``ApplicativeG<'T>`` -> '``ApplicativeG<'U>`` -> '``ApplicativeG<'V>``) x y: '``ApplicativeF<'ApplicativeG<'V>``)
From 079f4443d7758753e97bc7a68617719c589bc01e Mon Sep 17 00:00:00 2001
From: gusty <1261319+gusty@users.noreply.github.com>
Date: Thu, 8 Jan 2026 20:46:35 +0100
Subject: [PATCH 3/4] Fix forward/backward applicatives in Compose
---
src/FSharpPlus/Data/Compose.fs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/FSharpPlus/Data/Compose.fs b/src/FSharpPlus/Data/Compose.fs
index 0423178a7..a1345c01d 100644
--- a/src/FSharpPlus/Data/Compose.fs
+++ b/src/FSharpPlus/Data/Compose.fs
@@ -18,7 +18,7 @@ type Compose<'``functorF<'functorG<'t>>``> = Compose of '``functorF<'functorG<'t
/// To be used in Applicative Style expressions, combined with <*>
///
/// Functor
- static member inline () (f: 'T -> 'U, x: '``FunctorF<'FunctorG<'T>>``) =
+ static member inline () (f: 'T -> 'U, Compose (x: '``FunctorF<'FunctorG<'T>>``)) =
Compose (map (map f: '``FunctorG<'T>`` -> '``FunctorG<'U>``) x : '``FunctorF<'FunctorG<'U>>``)
// Applicative
@@ -32,15 +32,15 @@ type Compose<'``functorF<'functorG<'t>>``> = Compose of '``functorF<'functorG<'t
/// Sequences two composed applicatives left-to-right, discarding the value of the first argument.
///
/// Applicative
- static member inline ( *>) (x: '``FunctorF<'FunctorG<'T>>``, y: '``FunctorF<'FunctorG<'U>>``) : '``FunctorF<'FunctorG<'U>>`` =
- ((fun (_: 'T) (k: 'U) -> k) x : '``FunctorF<'FunctorG<'U -> 'U>>``) <*> y
+ static member inline ( *>) (Compose (x: '``FunctorF<'FunctorG<'T>>``), Compose (y: '``FunctorF<'FunctorG<'U>>``)) : Compose<'``FunctorF<'FunctorG<'U>>``> =
+ (Apply.Invoke << Map.Invoke (Apply.Invoke << Map.Invoke (fun _ k -> k))) x y |> Compose
///
/// Sequences two composed applicatives left-to-right, discarding the value of the second argument.
///
/// Applicative
- static member inline (<* ) (x: '``FunctorF<'FunctorG<'U>>``, y: '``FunctorF<'FunctorG<'T>>``): '``FunctorF<'FunctorG<'U>>`` =
- ((fun (k: 'U) (_: 'T) -> k) x : '``FunctorF<'FunctorG<'T -> 'U>>``) <*> y
+ static member inline (<* ) (Compose (x: '``FunctorF<'FunctorG<'U>>``), Compose (y: '``FunctorF<'FunctorG<'T>>``)) : Compose<'``FunctorF<'FunctorG<'U>>``> =
+ (Apply.Invoke << Map.Invoke (Apply.Invoke << Map.Invoke (fun k _ -> k))) x y |> Compose
static member inline Lift2 (f: 'T -> 'U -> 'V, Compose (x: '``ApplicativeF<'ApplicativeG<'T>``), Compose (y: '``ApplicativeF<'ApplicativeG<'U>``)) =
Compose (Lift2.Invoke (Lift2.Invoke f: '``ApplicativeG<'T>`` -> '``ApplicativeG<'U>`` -> '``ApplicativeG<'V>``) x y: '``ApplicativeF<'ApplicativeG<'V>``)
From afc8a4e57d4ad73edd885dfecc508e1ef8121704 Mon Sep 17 00:00:00 2001
From: gusty <1261319+gusty@users.noreply.github.com>
Date: Fri, 9 Jan 2026 08:45:50 +0100
Subject: [PATCH 4/4] Improve type inference
---
src/FSharpPlus/Operators.fs | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/FSharpPlus/Operators.fs b/src/FSharpPlus/Operators.fs
index 3b241069b..ad597a92e 100644
--- a/src/FSharpPlus/Operators.fs
+++ b/src/FSharpPlus/Operators.fs
@@ -217,13 +217,13 @@ module Operators =
/// Sequences two applicatives left-to-right, discarding the value of the first argument.
///
/// Applicative
- let inline ( *>) (x: '``Applicative<'T>``) (y: '``Applicative<'U>``) : '``Applicative<'U>`` = ((fun (_: 'T) (k: 'U) -> k) x : '``Applicative<'U->'U>``) <*> y
+ let inline ( *>) (x: '``Applicative<'T>``) (y: '``Applicative<'U>``) : '``Applicative< 'U>`` = ((fun (_: 'T) (k: 'U) -> k) x : '``Applicative<'U->'U>``) <*> y
///
/// Sequences two applicatives left-to-right, discarding the value of the second argument.
///
/// Applicative
- let inline (<* ) (x: '``Applicative<'U>``) (y: '``Applicative<'T>``) : '``Applicative<'U>`` = ((fun (k: 'U) (_: 'T) -> k ) x : '``Applicative<'T->'U>``) <*> y
+ let inline (<* ) (x: '``Applicative<'U>``) (y: '``Applicative<'T>``) : '``Applicative< 'U>`` = ((fun (k: 'U) (_: 'T) -> k ) x : '``Applicative<'T->'U>``) <*> y
///
/// Transforms an alternative value (which has the notion of success/failure) to an alternative
@@ -262,36 +262,36 @@ module Operators =
/// Applies two applicatives left-to-right in a non-sequential way, discarding the value of the first argument.
///
/// Applicative
- let inline (.>) (x: '``ZipApplicative<'T>``) (y: '``ZipApplicative<'U>``) : '``ZipApplicative<'U>`` = ((fun (_: 'T) (k: 'U) -> k) x : '``ZipApplicative<'U->'U>``) <.> y
+ let inline (.>) (x: '``ZipApplicative<'T>``) (y: '``ZipApplicative<'U>``) : '``ZipApplicative< 'U>`` = ((fun (_: 'T) (k: 'U) -> k) x : '``ZipApplicative<'U->'U>``) <.> y
///
/// Applies two applicatives left-to-right in a non-sequential way, discarding the value of the second argument.
///
/// Applicative
- let inline (<.) (x: '``ZipApplicative<'U>``) (y: '``ZipApplicative<'T>``) : '``ZipApplicative<'U>`` = ((fun (k: 'U) (_: 'T) -> k ) x : '``ZipApplicative<'T->'U>``) <.> y
+ let inline (<.) (x: '``ZipApplicative<'U>``) (y: '``ZipApplicative<'T>``) : '``ZipApplicative< 'U>`` = ((fun (k: 'U) (_: 'T) -> k ) x : '``ZipApplicative<'T->'U>``) <.> y
///
/// Sequences two nested applicatives left-to-right, discarding the value of the first argument.
///
/// Applicative
- let inline ( **>) (x: '``Applicative1>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( *>) x) <*> y
+ let inline ( **>) (x: '``Applicative1>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( *>) x) <*> y
///
/// Applies two nested applicatives left-to-right, discarding the value of the first argument.
/// The outer applicative is non-sequential (zip-like), while the inner one is sequential.
///
- let inline ( .*>) (x: '``ZipApplicative>``) (y: '``ZipApplicative>``) : '``ZipApplicative1>`` = (Map.Invoke ( *>) x) <.> y
+ let inline ( .*>) (x: '``ZipApplicative>``) (y: '``ZipApplicative>``) : '``ZipApplicative1>`` = (Map.Invoke ( *>) x) <.> y
///
/// Applies two nested applicatives left-to-right, discarding the value of the first argument.
/// The outer applicative is sequential, while the inner one is non-sequential (zip-like).
///
- let inline ( *.>) (x: '``Applicative>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( .>) x) <*> y
+ let inline ( *.>) (x: '``Applicative>``) (y: '``Applicative1>``) : '``Applicative1>`` = (Map.Invoke ( .>) x) <*> y
///
/// Applies two nested applicatives left-to-right in a non-sequential way, discarding the value of the first argument.
///
- let inline ( ..>) (x: '``ZipApplicative1>``) (y: '``ZipApplicative1>``) : '``ZipApplicative1>`` = (Map.Invoke ( .>) x) <.> y
+ let inline ( ..>) (x: '``ZipApplicative1>``) (y: '``ZipApplicative1>``) : '``ZipApplicative1>`` = (Map.Invoke ( .>) x) <.> y
///
/// Applies 2 lifted arguments to a non-lifted function with pointwise and/or parallel semantics.