1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-12-09 23:11:40 +02:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Dr. Carsten Leue
2f99ca471a fix: add example for dependency injection using a Reader
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-04 21:52:50 +01:00
Dr. Carsten Leue
3e09a19d68 fix: Writer monad
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-01 22:11:29 +01:00
Dr. Carsten Leue
839ef47054 fix: refactor writer
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-01 18:26:09 +01:00
Dr. Carsten Leue
144b27233b fix: some internal refactorings
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-01 17:26:51 +01:00
Dr. Carsten Leue
668eb85aea fix: some smaller optimizations
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-01 09:08:31 +01:00
33 changed files with 1531 additions and 1281 deletions

View File

@@ -344,7 +344,7 @@ func MonadFlap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](fab GFAB, a A) GB
} }
func Flap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](a A) func(GFAB) GB { func Flap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](a A) func(GFAB) GB {
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a) return FC.Flap(Map[GFAB, GB], a)
} }
func Prepend[ENDO ~func(AS) AS, AS []A, A any](head A) ENDO { func Prepend[ENDO ~func(AS) AS, AS []A, A any](head A) ENDO {

View File

@@ -64,7 +64,7 @@ func MonadMapTo[E, A, B any](fa Either[E, A], b B) Either[E, B] {
} }
func MapTo[E, A, B any](b B) func(Either[E, A]) Either[E, B] { func MapTo[E, A, B any](b B) func(Either[E, A]) Either[E, B] {
return F.Bind2nd(MonadMapTo[E, A, B], b) return Map[E](F.Constant1[A](b))
} }
func MonadMapLeft[E1, A, E2 any](fa Either[E1, A], f func(E1) E2) Either[E2, A] { func MonadMapLeft[E1, A, E2 any](fa Either[E1, A], f func(E1) E2) Either[E2, A] {
@@ -77,7 +77,7 @@ func Map[E, A, B any](f func(a A) B) func(fa Either[E, A]) Either[E, B] {
// MapLeft applies a mapping function to the error channel // MapLeft applies a mapping function to the error channel
func MapLeft[A, E1, E2 any](f func(E1) E2) func(fa Either[E1, A]) Either[E2, A] { func MapLeft[A, E1, E2 any](f func(E1) E2) func(fa Either[E1, A]) Either[E2, A] {
return F.Bind2nd(MonadMapLeft[E1, A, E2], f) return Fold(F.Flow2(f, Left[A, E2]), Right[E2, A])
} }
func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] { func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] {
@@ -106,11 +106,11 @@ func ChainOptionK[A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(E
} }
func ChainTo[A, E, B any](mb Either[E, B]) func(Either[E, A]) Either[E, B] { func ChainTo[A, E, B any](mb Either[E, B]) func(Either[E, A]) Either[E, B] {
return F.Bind2nd(MonadChainTo[A, E, B], mb) return F.Constant1[Either[E, A]](mb)
} }
func Chain[E, A, B any](f func(a A) Either[E, B]) func(Either[E, A]) Either[E, B] { func Chain[E, A, B any](f func(a A) Either[E, B]) func(Either[E, A]) Either[E, B] {
return F.Bind2nd(MonadChain[E, A, B], f) return Fold(Left[B, E], f)
} }
func ChainFirst[E, A, B any](f func(a A) Either[E, B]) func(Either[E, A]) Either[E, A] { func ChainFirst[E, A, B any](f func(a A) Either[E, B]) func(Either[E, A]) Either[E, A] {
@@ -251,7 +251,7 @@ func MonadFlap[E, B, A any](fab Either[E, func(A) B], a A) Either[E, B] {
} }
func Flap[E, B, A any](a A) func(Either[E, func(A) B]) Either[E, B] { func Flap[E, B, A any](a A) func(Either[E, func(A) B]) Either[E, B] {
return F.Bind2nd(MonadFlap[E, B, A], a) return FC.Flap(Map[E, func(A) B, B], a)
} }
func MonadAlt[E, A any](fa Either[E, A], that L.Lazy[Either[E, A]]) Either[E, A] { func MonadAlt[E, A any](fa Either[E, A], that L.Lazy[Either[E, A]]) Either[E, A] {

View File

@@ -3,449 +3,453 @@
// 2024-01-31 21:45:01.6437619 +0100 CET m=+0.032758901 // 2024-01-31 21:45:01.6437619 +0100 CET m=+0.032758901
package function package function
// Combinations for a total of 1 arguments // Combinations for a total of 1 arguments
// Bind1of1 takes a function with 1 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function. // Bind1of1 takes a function with 1 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function.
// The return value of is a function with the remaining 0 parameters at positions [] of the original function. // The return value of is a function with the remaining 0 parameters at positions [] of the original function.
func Bind1of1[F ~func(T1) R, T1, R any](f F) func(T1) func() R { func Bind1of1[F ~func(T1) R, T1, R any](f F) func(T1) func() R {
return func(t1 T1) func() R { return func(t1 T1) func() R {
return func() R { return func() R {
return f(t1) return f(t1)
} }
} }
} }
// Ignore1of1 takes a function with 0 parameters and returns a new function with 1 parameters that will ignore the values at positions [1] and pass the remaining 0 parameters to the original function // Ignore1of1 takes a function with 0 parameters and returns a new function with 1 parameters that will ignore the values at positions [1] and pass the remaining 0 parameters to the original function
func Ignore1of1[T1 any, F ~func() R, R any](f F) func(T1) R { func Ignore1of1[T1 any, F ~func() R, R any](f F) func(T1) R {
return func(t1 T1) R { return func(t1 T1) R {
return f() return f()
} }
} }
// Combinations for a total of 2 arguments // Combinations for a total of 2 arguments
// Bind1of2 takes a function with 2 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function. // Bind1of2 takes a function with 2 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [2] of the original function. // The return value of is a function with the remaining 1 parameters at positions [2] of the original function.
func Bind1of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T1) func(T2) R { func Bind1of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T1) func(T2) R {
return func(t1 T1) func(T2) R { return func(t1 T1) func(T2) R {
return func(t2 T2) R { return func(t2 T2) R {
return f(t1, t2) return f(t1, t2)
} }
} }
} }
// Ignore1of2 takes a function with 1 parameters and returns a new function with 2 parameters that will ignore the values at positions [1] and pass the remaining 1 parameters to the original function // Ignore1of2 takes a function with 1 parameters and returns a new function with 2 parameters that will ignore the values at positions [1] and pass the remaining 1 parameters to the original function
func Ignore1of2[T1 any, F ~func(T2) R, T2, R any](f F) func(T1, T2) R { func Ignore1of2[T1 any, F ~func(T2) R, T2, R any](f F) func(T1, T2) R {
return func(t1 T1, t2 T2) R { return func(t1 T1, t2 T2) R {
return f(t2) return f(t2)
} }
} }
// Bind2of2 takes a function with 2 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function. // Bind2of2 takes a function with 2 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [1] of the original function. // The return value of is a function with the remaining 1 parameters at positions [1] of the original function.
func Bind2of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T2) func(T1) R { func Bind2of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T2) func(T1) R {
return func(t2 T2) func(T1) R { return func(t2 T2) func(T1) R {
return func(t1 T1) R { return func(t1 T1) R {
return f(t1, t2) return f(t1, t2)
} }
} }
} }
// Ignore2of2 takes a function with 1 parameters and returns a new function with 2 parameters that will ignore the values at positions [2] and pass the remaining 1 parameters to the original function // Ignore2of2 takes a function with 1 parameters and returns a new function with 2 parameters that will ignore the values at positions [2] and pass the remaining 1 parameters to the original function
func Ignore2of2[T2 any, F ~func(T1) R, T1, R any](f F) func(T1, T2) R { func Ignore2of2[T2 any, F ~func(T1) R, T1, R any](f F) func(T1, T2) R {
return func(t1 T1, t2 T2) R { return func(t1 T1, t2 T2) R {
return f(t1) return f(t1)
} }
} }
// Bind12of2 takes a function with 2 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function. // Bind12of2 takes a function with 2 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function.
// The return value of is a function with the remaining 0 parameters at positions [] of the original function. // The return value of is a function with the remaining 0 parameters at positions [] of the original function.
func Bind12of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2) func() R { func Bind12of2[F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2) func() R {
return func(t1 T1, t2 T2) func() R { return func(t1 T1, t2 T2) func() R {
return func() R { return func() R {
return f(t1, t2) return f(t1, t2)
} }
} }
} }
// Ignore12of2 takes a function with 0 parameters and returns a new function with 2 parameters that will ignore the values at positions [1, 2] and pass the remaining 0 parameters to the original function // Ignore12of2 takes a function with 0 parameters and returns a new function with 2 parameters that will ignore the values at positions [1, 2] and pass the remaining 0 parameters to the original function
func Ignore12of2[T1, T2 any, F ~func() R, R any](f F) func(T1, T2) R { func Ignore12of2[T1, T2 any, F ~func() R, R any](f F) func(T1, T2) R {
return func(t1 T1, t2 T2) R { return func(t1 T1, t2 T2) R {
return f() return f()
} }
} }
// Combinations for a total of 3 arguments // Combinations for a total of 3 arguments
// Bind1of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function. // Bind1of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [2, 3] of the original function. // The return value of is a function with the remaining 2 parameters at positions [2, 3] of the original function.
func Bind1of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1) func(T2, T3) R { func Bind1of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1) func(T2, T3) R {
return func(t1 T1) func(T2, T3) R { return func(t1 T1) func(T2, T3) R {
return func(t2 T2, t3 T3) R { return func(t2 T2, t3 T3) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore1of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [1] and pass the remaining 2 parameters to the original function // Ignore1of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [1] and pass the remaining 2 parameters to the original function
func Ignore1of3[T1 any, F ~func(T2, T3) R, T2, T3, R any](f F) func(T1, T2, T3) R { func Ignore1of3[T1 any, F ~func(T2, T3) R, T2, T3, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t2, t3) return f(t2, t3)
} }
} }
// Bind2of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function. // Bind2of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [1, 3] of the original function. // The return value of is a function with the remaining 2 parameters at positions [1, 3] of the original function.
func Bind2of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T2) func(T1, T3) R { func Bind2of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T2) func(T1, T3) R {
return func(t2 T2) func(T1, T3) R { return func(t2 T2) func(T1, T3) R {
return func(t1 T1, t3 T3) R { return func(t1 T1, t3 T3) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore2of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [2] and pass the remaining 2 parameters to the original function // Ignore2of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [2] and pass the remaining 2 parameters to the original function
func Ignore2of3[T2 any, F ~func(T1, T3) R, T1, T3, R any](f F) func(T1, T2, T3) R { func Ignore2of3[T2 any, F ~func(T1, T3) R, T1, T3, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t1, t3) return f(t1, t3)
} }
} }
// Bind3of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [3] of the original function. // Bind3of3 takes a function with 3 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [3] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [1, 2] of the original function. // The return value of is a function with the remaining 2 parameters at positions [1, 2] of the original function.
func Bind3of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T3) func(T1, T2) R { func Bind3of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T3) func(T1, T2) R {
return func(t3 T3) func(T1, T2) R { return func(t3 T3) func(T1, T2) R {
return func(t1 T1, t2 T2) R { return func(t1 T1, t2 T2) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore3of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [3] and pass the remaining 2 parameters to the original function // Ignore3of3 takes a function with 2 parameters and returns a new function with 3 parameters that will ignore the values at positions [3] and pass the remaining 2 parameters to the original function
func Ignore3of3[T3 any, F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2, T3) R { func Ignore3of3[T3 any, F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t1, t2) return f(t1, t2)
} }
} }
// Bind12of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function. // Bind12of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [3] of the original function. // The return value of is a function with the remaining 1 parameters at positions [3] of the original function.
func Bind12of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2) func(T3) R { func Bind12of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2) func(T3) R {
return func(t1 T1, t2 T2) func(T3) R { return func(t1 T1, t2 T2) func(T3) R {
return func(t3 T3) R { return func(t3 T3) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore12of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 2] and pass the remaining 1 parameters to the original function // Ignore12of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 2] and pass the remaining 1 parameters to the original function
func Ignore12of3[T1, T2 any, F ~func(T3) R, T3, R any](f F) func(T1, T2, T3) R { func Ignore12of3[T1, T2 any, F ~func(T3) R, T3, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t3) return f(t3)
} }
} }
// Bind13of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 3] of the original function. // Bind13of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 3] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [2] of the original function. // The return value of is a function with the remaining 1 parameters at positions [2] of the original function.
func Bind13of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T3) func(T2) R { func Bind13of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T3) func(T2) R {
return func(t1 T1, t3 T3) func(T2) R { return func(t1 T1, t3 T3) func(T2) R {
return func(t2 T2) R { return func(t2 T2) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore13of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 3] and pass the remaining 1 parameters to the original function // Ignore13of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 3] and pass the remaining 1 parameters to the original function
func Ignore13of3[T1, T3 any, F ~func(T2) R, T2, R any](f F) func(T1, T2, T3) R { func Ignore13of3[T1, T3 any, F ~func(T2) R, T2, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t2) return f(t2)
} }
} }
// Bind23of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 3] of the original function. // Bind23of3 takes a function with 3 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 3] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [1] of the original function. // The return value of is a function with the remaining 1 parameters at positions [1] of the original function.
func Bind23of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T2, T3) func(T1) R { func Bind23of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T2, T3) func(T1) R {
return func(t2 T2, t3 T3) func(T1) R { return func(t2 T2, t3 T3) func(T1) R {
return func(t1 T1) R { return func(t1 T1) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore23of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [2, 3] and pass the remaining 1 parameters to the original function // Ignore23of3 takes a function with 1 parameters and returns a new function with 3 parameters that will ignore the values at positions [2, 3] and pass the remaining 1 parameters to the original function
func Ignore23of3[T2, T3 any, F ~func(T1) R, T1, R any](f F) func(T1, T2, T3) R { func Ignore23of3[T2, T3 any, F ~func(T1) R, T1, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t1) return f(t1)
} }
} }
// Bind123of3 takes a function with 3 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 3] of the original function. // Bind123of3 takes a function with 3 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 3] of the original function.
// The return value of is a function with the remaining 0 parameters at positions [] of the original function. // The return value of is a function with the remaining 0 parameters at positions [] of the original function.
func Bind123of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2, T3) func() R { func Bind123of3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2, T3) func() R {
return func(t1 T1, t2 T2, t3 T3) func() R { return func(t1 T1, t2 T2, t3 T3) func() R {
return func() R { return func() R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
} }
// Ignore123of3 takes a function with 0 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 2, 3] and pass the remaining 0 parameters to the original function // Ignore123of3 takes a function with 0 parameters and returns a new function with 3 parameters that will ignore the values at positions [1, 2, 3] and pass the remaining 0 parameters to the original function
func Ignore123of3[T1, T2, T3 any, F ~func() R, R any](f F) func(T1, T2, T3) R { func Ignore123of3[T1, T2, T3 any, F ~func() R, R any](f F) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f() return f()
} }
} }
// Combinations for a total of 4 arguments // Combinations for a total of 4 arguments
// Bind1of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function. // Bind1of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [1] of the original function.
// The return value of is a function with the remaining 3 parameters at positions [2, 3, 4] of the original function. // The return value of is a function with the remaining 3 parameters at positions [2, 3, 4] of the original function.
func Bind1of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1) func(T2, T3, T4) R { func Bind1of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1) func(T2, T3, T4) R {
return func(t1 T1) func(T2, T3, T4) R { return func(t1 T1) func(T2, T3, T4) R {
return func(t2 T2, t3 T3, t4 T4) R { return func(t2 T2, t3 T3, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore1of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [1] and pass the remaining 3 parameters to the original function // Ignore1of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [1] and pass the remaining 3 parameters to the original function
func Ignore1of4[T1 any, F ~func(T2, T3, T4) R, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore1of4[T1 any, F ~func(T2, T3, T4) R, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t2, t3, t4) return f(t2, t3, t4)
} }
} }
// Bind2of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function. // Bind2of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [2] of the original function.
// The return value of is a function with the remaining 3 parameters at positions [1, 3, 4] of the original function. // The return value of is a function with the remaining 3 parameters at positions [1, 3, 4] of the original function.
func Bind2of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2) func(T1, T3, T4) R { func Bind2of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2) func(T1, T3, T4) R {
return func(t2 T2) func(T1, T3, T4) R { return func(t2 T2) func(T1, T3, T4) R {
return func(t1 T1, t3 T3, t4 T4) R { return func(t1 T1, t3 T3, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore2of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [2] and pass the remaining 3 parameters to the original function // Ignore2of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [2] and pass the remaining 3 parameters to the original function
func Ignore2of4[T2 any, F ~func(T1, T3, T4) R, T1, T3, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore2of4[T2 any, F ~func(T1, T3, T4) R, T1, T3, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t3, t4) return f(t1, t3, t4)
} }
} }
// Bind3of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [3] of the original function. // Bind3of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [3] of the original function.
// The return value of is a function with the remaining 3 parameters at positions [1, 2, 4] of the original function. // The return value of is a function with the remaining 3 parameters at positions [1, 2, 4] of the original function.
func Bind3of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T3) func(T1, T2, T4) R { func Bind3of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T3) func(T1, T2, T4) R {
return func(t3 T3) func(T1, T2, T4) R { return func(t3 T3) func(T1, T2, T4) R {
return func(t1 T1, t2 T2, t4 T4) R { return func(t1 T1, t2 T2, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore3of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [3] and pass the remaining 3 parameters to the original function // Ignore3of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [3] and pass the remaining 3 parameters to the original function
func Ignore3of4[T3 any, F ~func(T1, T2, T4) R, T1, T2, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore3of4[T3 any, F ~func(T1, T2, T4) R, T1, T2, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t2, t4) return f(t1, t2, t4)
} }
} }
// Bind4of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [4] of the original function. // Bind4of4 takes a function with 4 parameters and returns a new function with 1 parameters that will bind these parameters to the positions [4] of the original function.
// The return value of is a function with the remaining 3 parameters at positions [1, 2, 3] of the original function. // The return value of is a function with the remaining 3 parameters at positions [1, 2, 3] of the original function.
func Bind4of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T4) func(T1, T2, T3) R { func Bind4of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T4) func(T1, T2, T3) R {
return func(t4 T4) func(T1, T2, T3) R { return func(t4 T4) func(T1, T2, T3) R {
return func(t1 T1, t2 T2, t3 T3) R { return func(t1 T1, t2 T2, t3 T3) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore4of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [4] and pass the remaining 3 parameters to the original function // Ignore4of4 takes a function with 3 parameters and returns a new function with 4 parameters that will ignore the values at positions [4] and pass the remaining 3 parameters to the original function
func Ignore4of4[T4 any, F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2, T3, T4) R { func Ignore4of4[T4 any, F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t2, t3) return f(t1, t2, t3)
} }
} }
// Bind12of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function. // Bind12of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 2] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [3, 4] of the original function. // The return value of is a function with the remaining 2 parameters at positions [3, 4] of the original function.
func Bind12of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2) func(T3, T4) R { func Bind12of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2) func(T3, T4) R {
return func(t1 T1, t2 T2) func(T3, T4) R { return func(t1 T1, t2 T2) func(T3, T4) R {
return func(t3 T3, t4 T4) R { return func(t3 T3, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore12of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2] and pass the remaining 2 parameters to the original function // Ignore12of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2] and pass the remaining 2 parameters to the original function
func Ignore12of4[T1, T2 any, F ~func(T3, T4) R, T3, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore12of4[T1, T2 any, F ~func(T3, T4) R, T3, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t3, t4) return f(t3, t4)
} }
} }
// Bind13of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 3] of the original function. // Bind13of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 3] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [2, 4] of the original function. // The return value of is a function with the remaining 2 parameters at positions [2, 4] of the original function.
func Bind13of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T3) func(T2, T4) R { func Bind13of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T3) func(T2, T4) R {
return func(t1 T1, t3 T3) func(T2, T4) R { return func(t1 T1, t3 T3) func(T2, T4) R {
return func(t2 T2, t4 T4) R { return func(t2 T2, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore13of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 3] and pass the remaining 2 parameters to the original function // Ignore13of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 3] and pass the remaining 2 parameters to the original function
func Ignore13of4[T1, T3 any, F ~func(T2, T4) R, T2, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore13of4[T1, T3 any, F ~func(T2, T4) R, T2, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t2, t4) return f(t2, t4)
} }
} }
// Bind14of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 4] of the original function. // Bind14of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [1, 4] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [2, 3] of the original function. // The return value of is a function with the remaining 2 parameters at positions [2, 3] of the original function.
func Bind14of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T4) func(T2, T3) R { func Bind14of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T4) func(T2, T3) R {
return func(t1 T1, t4 T4) func(T2, T3) R { return func(t1 T1, t4 T4) func(T2, T3) R {
return func(t2 T2, t3 T3) R { return func(t2 T2, t3 T3) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore14of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 4] and pass the remaining 2 parameters to the original function // Ignore14of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 4] and pass the remaining 2 parameters to the original function
func Ignore14of4[T1, T4 any, F ~func(T2, T3) R, T2, T3, R any](f F) func(T1, T2, T3, T4) R { func Ignore14of4[T1, T4 any, F ~func(T2, T3) R, T2, T3, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t2, t3) return f(t2, t3)
} }
} }
// Bind23of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 3] of the original function. // Bind23of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 3] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [1, 4] of the original function. // The return value of is a function with the remaining 2 parameters at positions [1, 4] of the original function.
func Bind23of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T3) func(T1, T4) R { func Bind23of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T3) func(T1, T4) R {
return func(t2 T2, t3 T3) func(T1, T4) R { return func(t2 T2, t3 T3) func(T1, T4) R {
return func(t1 T1, t4 T4) R { return func(t1 T1, t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore23of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 3] and pass the remaining 2 parameters to the original function // Ignore23of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 3] and pass the remaining 2 parameters to the original function
func Ignore23of4[T2, T3 any, F ~func(T1, T4) R, T1, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore23of4[T2, T3 any, F ~func(T1, T4) R, T1, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t4) return f(t1, t4)
} }
} }
// Bind24of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 4] of the original function. // Bind24of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [2, 4] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [1, 3] of the original function. // The return value of is a function with the remaining 2 parameters at positions [1, 3] of the original function.
func Bind24of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T4) func(T1, T3) R { func Bind24of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T4) func(T1, T3) R {
return func(t2 T2, t4 T4) func(T1, T3) R { return func(t2 T2, t4 T4) func(T1, T3) R {
return func(t1 T1, t3 T3) R { return func(t1 T1, t3 T3) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore24of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 4] and pass the remaining 2 parameters to the original function // Ignore24of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 4] and pass the remaining 2 parameters to the original function
func Ignore24of4[T2, T4 any, F ~func(T1, T3) R, T1, T3, R any](f F) func(T1, T2, T3, T4) R { func Ignore24of4[T2, T4 any, F ~func(T1, T3) R, T1, T3, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t3) return f(t1, t3)
} }
} }
// Bind34of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [3, 4] of the original function. // Bind34of4 takes a function with 4 parameters and returns a new function with 2 parameters that will bind these parameters to the positions [3, 4] of the original function.
// The return value of is a function with the remaining 2 parameters at positions [1, 2] of the original function. // The return value of is a function with the remaining 2 parameters at positions [1, 2] of the original function.
func Bind34of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T3, T4) func(T1, T2) R { func Bind34of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T3, T4) func(T1, T2) R {
return func(t3 T3, t4 T4) func(T1, T2) R { return func(t3 T3, t4 T4) func(T1, T2) R {
return func(t1 T1, t2 T2) R { return func(t1 T1, t2 T2) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore34of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [3, 4] and pass the remaining 2 parameters to the original function // Ignore34of4 takes a function with 2 parameters and returns a new function with 4 parameters that will ignore the values at positions [3, 4] and pass the remaining 2 parameters to the original function
func Ignore34of4[T3, T4 any, F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2, T3, T4) R { func Ignore34of4[T3, T4 any, F ~func(T1, T2) R, T1, T2, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1, t2) return f(t1, t2)
} }
} }
// Bind123of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 3] of the original function. // Bind123of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 3] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [4] of the original function. // The return value of is a function with the remaining 1 parameters at positions [4] of the original function.
func Bind123of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T3) func(T4) R { func Bind123of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T3) func(T4) R {
return func(t1 T1, t2 T2, t3 T3) func(T4) R { return func(t1 T1, t2 T2, t3 T3) func(T4) R {
return func(t4 T4) R { return func(t4 T4) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore123of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 3] and pass the remaining 1 parameters to the original function // Ignore123of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 3] and pass the remaining 1 parameters to the original function
func Ignore123of4[T1, T2, T3 any, F ~func(T4) R, T4, R any](f F) func(T1, T2, T3, T4) R { func Ignore123of4[T1, T2, T3 any, F ~func(T4) R, T4, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t4) return f(t4)
} }
} }
// Bind124of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 4] of the original function. // Bind124of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 2, 4] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [3] of the original function. // The return value of is a function with the remaining 1 parameters at positions [3] of the original function.
func Bind124of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T4) func(T3) R { func Bind124of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T4) func(T3) R {
return func(t1 T1, t2 T2, t4 T4) func(T3) R { return func(t1 T1, t2 T2, t4 T4) func(T3) R {
return func(t3 T3) R { return func(t3 T3) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore124of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 4] and pass the remaining 1 parameters to the original function // Ignore124of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 4] and pass the remaining 1 parameters to the original function
func Ignore124of4[T1, T2, T4 any, F ~func(T3) R, T3, R any](f F) func(T1, T2, T3, T4) R { func Ignore124of4[T1, T2, T4 any, F ~func(T3) R, T3, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t3) return f(t3)
} }
} }
// Bind134of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 3, 4] of the original function. // Bind134of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [1, 3, 4] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [2] of the original function. // The return value of is a function with the remaining 1 parameters at positions [2] of the original function.
func Bind134of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T3, T4) func(T2) R { func Bind134of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T3, T4) func(T2) R {
return func(t1 T1, t3 T3, t4 T4) func(T2) R { return func(t1 T1, t3 T3, t4 T4) func(T2) R {
return func(t2 T2) R { return func(t2 T2) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore134of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 3, 4] and pass the remaining 1 parameters to the original function // Ignore134of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 3, 4] and pass the remaining 1 parameters to the original function
func Ignore134of4[T1, T3, T4 any, F ~func(T2) R, T2, R any](f F) func(T1, T2, T3, T4) R { func Ignore134of4[T1, T3, T4 any, F ~func(T2) R, T2, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t2) return f(t2)
} }
} }
// Bind234of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [2, 3, 4] of the original function. // Bind234of4 takes a function with 4 parameters and returns a new function with 3 parameters that will bind these parameters to the positions [2, 3, 4] of the original function.
// The return value of is a function with the remaining 1 parameters at positions [1] of the original function. // The return value of is a function with the remaining 1 parameters at positions [1] of the original function.
func Bind234of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T3, T4) func(T1) R { func Bind234of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T2, T3, T4) func(T1) R {
return func(t2 T2, t3 T3, t4 T4) func(T1) R { return func(t2 T2, t3 T3, t4 T4) func(T1) R {
return func(t1 T1) R { return func(t1 T1) R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore234of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 3, 4] and pass the remaining 1 parameters to the original function // Ignore234of4 takes a function with 1 parameters and returns a new function with 4 parameters that will ignore the values at positions [2, 3, 4] and pass the remaining 1 parameters to the original function
func Ignore234of4[T2, T3, T4 any, F ~func(T1) R, T1, R any](f F) func(T1, T2, T3, T4) R { func Ignore234of4[T2, T3, T4 any, F ~func(T1) R, T1, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f(t1) return f(t1)
} }
} }
// Bind1234of4 takes a function with 4 parameters and returns a new function with 4 parameters that will bind these parameters to the positions [1, 2, 3, 4] of the original function. // Bind1234of4 takes a function with 4 parameters and returns a new function with 4 parameters that will bind these parameters to the positions [1, 2, 3, 4] of the original function.
// The return value of is a function with the remaining 0 parameters at positions [] of the original function. // The return value of is a function with the remaining 0 parameters at positions [] of the original function.
func Bind1234of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) func() R { func Bind1234of4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) func() R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) func() R { return func(t1 T1, t2 T2, t3 T3, t4 T4) func() R {
return func() R { return func() R {
return f(t1, t2, t3, t4) return f(t1, t2, t3, t4)
} }
} }
} }
// Ignore1234of4 takes a function with 0 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 3, 4] and pass the remaining 0 parameters to the original function // Ignore1234of4 takes a function with 0 parameters and returns a new function with 4 parameters that will ignore the values at positions [1, 2, 3, 4] and pass the remaining 0 parameters to the original function
func Ignore1234of4[T1, T2, T3, T4 any, F ~func() R, R any](f F) func(T1, T2, T3, T4) R { func Ignore1234of4[T1, T2, T3, T4 any, F ~func() R, R any](f F) func(T1, T2, T3, T4) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4) R { return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
return f() return f()
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,11 @@ func MonadChainFirst[GAB ~func(A) B, A, B any](fa A, f GAB) A {
} }
func ChainFirst[GAB ~func(A) B, A, B any](f GAB) func(A) A { func ChainFirst[GAB ~func(A) B, A, B any](f GAB) func(A) A {
return C.ChainFirst(MonadChain[func(A) A, A, A], MonadMap[func(B) A, B, A], f) return C.ChainFirst(
Chain[func(A) A, A, A],
Map[func(B) A, B, A],
f,
)
} }
func MonadFlap[GAB ~func(A) B, A, B any](fab GAB, a A) B { func MonadFlap[GAB ~func(A) B, A, B any](fab GAB, a A) B {
@@ -58,5 +62,5 @@ func MonadFlap[GAB ~func(A) B, A, B any](fab GAB, a A) B {
} }
func Flap[GAB ~func(A) B, B, A any](a A) func(GAB) B { func Flap[GAB ~func(A) B, B, A any](a A) func(GAB) B {
return F.Bind2nd(MonadFlap[GAB, A, B], a) return FC.Flap(Map[func(GAB) B, GAB, B], a)
} }

View File

@@ -19,13 +19,6 @@ import (
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
) )
// HKTFGA = HKT<F, HKT<G, A>>
// HKTFGB = HKT<F, HKT<G, B>>
// HKTFGAB = HKT<F, HKT<G, (a: A) => B>>
// HKTGA = HKT<G, A>
// HKTGB = HKT<G, B>
// HKTGAB = HKT<G, (a: A) => B>
func MonadAp[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any]( func MonadAp[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
fap func(HKTFGGAB, HKTFGA) HKTFGB, fap func(HKTFGGAB, HKTFGA) HKTFGB,
fmap func(HKTFGAB, func(HKTGAB) func(HKTGA) HKTGB) HKTFGGAB, fmap func(HKTFGAB, func(HKTGAB) func(HKTGA) HKTGB) HKTFGGAB,
@@ -37,6 +30,19 @@ func MonadAp[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
return fap(fmap(fab, F.Bind1st(F.Bind1st[HKTGAB, HKTGA, HKTGB], gap)), fa) return fap(fmap(fab, F.Bind1st(F.Bind1st[HKTGAB, HKTGA, HKTGB], gap)), fa)
} }
func Ap[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
fap func(HKTFGA) func(HKTFGGAB) HKTFGB,
fmap func(func(HKTGAB) func(HKTGA) HKTGB) func(HKTFGAB) HKTFGGAB,
gap func(HKTGA) func(HKTGAB) HKTGB,
fa HKTFGA) func(HKTFGAB) HKTFGB {
return F.Flow2(
fmap(F.Flip(gap)),
fap(fa),
)
}
// func Ap[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any]( // func Ap[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
// fap func(HKTFGA) func(HKTFGGAB) HKTFGB, // fap func(HKTFGA) func(HKTFGGAB) HKTFGB,
// fmap func(func(HKTGAB) func(HKTGA) HKTGB) func(HKTFGAB) HKTFGGAB, // fmap func(func(HKTGAB) func(HKTGA) HKTGB) func(HKTFGAB) HKTFGGAB,

View File

@@ -43,11 +43,11 @@ func MonadChain[A, B, HKTA, HKTB any](
// HKTA=HKT[A] // HKTA=HKT[A]
// HKTB=HKT[B] // HKTB=HKT[B]
func ChainFirst[A, B, HKTA, HKTB any]( func ChainFirst[A, B, HKTA, HKTB any](
mchain func(HKTA, func(A) HKTA) HKTA, mchain func(func(A) HKTA) func(HKTA) HKTA,
mmap func(HKTB, func(B) A) HKTA, mmap func(func(B) A) func(HKTB) HKTA,
f func(A) HKTB) func(HKTA) HKTA { f func(A) HKTB) func(HKTA) HKTA {
return F.Bind2nd(mchain, func(a A) HKTA { return mchain(func(a A) HKTA {
return mmap(f(a), F.Constant1[B](a)) return mmap(F.Constant1[B](a))(f(a))
}) })
} }

View File

@@ -51,6 +51,14 @@ func MonadMap[E, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E, A])
return FC.MonadMap(fmap, ET.MonadMap[E, A, B], fa, f) return FC.MonadMap(fmap, ET.MonadMap[E, A, B], fa, f)
} }
func Map[E, A, B, HKTFA, HKTFB any](
fmap func(func(ET.Either[E, A]) ET.Either[E, B]) func(HKTFA) HKTFB,
f func(A) B) func(HKTFA) HKTFB {
// HKTGA = Either[E, A]
// HKTGB = Either[E, B]
return FC.Map(fmap, ET.Map[E, A, B], f)
}
// HKTFA = HKT<F, Either<E, A>> // HKTFA = HKT<F, Either<E, A>>
// HKTFB = HKT<F, Either<E, B>> // HKTFB = HKT<F, Either<E, B>>
func MonadBiMap[E1, E2, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E1, A]) ET.Either[E2, B]) HKTFB, fa HKTFA, f func(E1) E2, g func(A) B) HKTFB { func MonadBiMap[E1, E2, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E1, A]) ET.Either[E2, B]) HKTFB, fa HKTFA, f func(E1) E2, g func(A) B) HKTFB {
@@ -61,10 +69,12 @@ func MonadBiMap[E1, E2, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[
// HKTFA = HKT<F, Either<E, A>> // HKTFA = HKT<F, Either<E, A>>
// HKTFB = HKT<F, Either<E, B>> // HKTFB = HKT<F, Either<E, B>>
func BiMap[E1, E2, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E1, A]) ET.Either[E2, B]) HKTFB, f func(E1) E2, g func(A) B) func(HKTFA) HKTFB { func BiMap[E1, E2, A, B, HKTFA, HKTFB any](
fmap func(func(ET.Either[E1, A]) ET.Either[E2, B]) func(HKTFA) HKTFB,
f func(E1) E2, g func(A) B) func(HKTFA) HKTFB {
// HKTGA = Either[E, A] // HKTGA = Either[E, A]
// HKTGB = Either[E, B] // HKTGB = Either[E, B]
return F.Bind2nd(fmap, ET.BiMap(f, g)) return fmap(ET.BiMap(f, g))
} }
// HKTFA = HKT<F, Either<E, A>> // HKTFA = HKT<F, Either<E, A>>
@@ -78,22 +88,29 @@ func MonadChain[E, A, B, HKTFA, HKTFB any](
return fchain(ma, ET.Fold(F.Flow2(ET.Left[B, E], fof), f)) return fchain(ma, ET.Fold(F.Flow2(ET.Left[B, E], fof), f))
} }
// func(fa func(R) T.Task[ET.Either[E, func(A) B]], f func(ET.Either[E, func(A) B]) func(ET.Either[E, A]) ET.Either[E, B]) GEFAB func Chain[E, A, B, HKTFA, HKTFB any](
fchain func(func(ET.Either[E, A]) HKTFB) func(HKTFA) HKTFB,
fof func(ET.Either[E, B]) HKTFB,
f func(A) HKTFB) func(HKTFA) HKTFB {
// dispatch to the even more generic implementation
return fchain(ET.Fold(F.Flow2(ET.Left[B, E], fof), f))
}
// HKTFA = HKT[Either[E, A]]
// HKTFB = HKT[Either[E, B]]
// HKTFAB = HKT[Either[E, func(A)B]]
func MonadAp[E, A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any]( func MonadAp[E, A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
fap func(HKTFGAB, HKTFA) HKTFB, fap func(HKTFGAB, HKTFA) HKTFB,
fmap func(HKTFAB, func(ET.Either[E, func(A) B]) func(ET.Either[E, A]) ET.Either[E, B]) HKTFGAB, fmap func(HKTFAB, func(ET.Either[E, func(A) B]) func(ET.Either[E, A]) ET.Either[E, B]) HKTFGAB,
fab HKTFAB, fab HKTFAB,
fa HKTFA) HKTFB { fa HKTFA) HKTFB {
// HKTGA = ET.Either[E, A]
// HKTGB = ET.Either[E, B]
// HKTGAB = ET.Either[E, func(a A) B]
return apply.MonadAp(fap, fmap, ET.MonadAp[B, E, A], fab, fa) return apply.MonadAp(fap, fmap, ET.MonadAp[B, E, A], fab, fa)
} }
func Ap[E, A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
fap func(HKTFA) func(HKTFGAB) HKTFB,
fmap func(func(ET.Either[E, func(A) B]) func(ET.Either[E, A]) ET.Either[E, B]) func(HKTFAB) HKTFGAB,
fa HKTFA) func(HKTFAB) HKTFB {
return apply.Ap(fap, fmap, ET.Ap[B, E, A], fa)
}
func Right[E, A, HKTA any](fof func(ET.Either[E, A]) HKTA, a A) HKTA { func Right[E, A, HKTA any](fof func(ET.Either[E, A]) HKTA, a A) HKTA {
return F.Pipe2(a, ET.Right[E, A], fof) return F.Pipe2(a, ET.Right[E, A], fof)
} }

View File

@@ -60,6 +60,13 @@ func MonadChainEitherK[A, E, B, HKTEA, HKTEB any](
return mchain(ma, F.Flow2(f, fromEither)) return mchain(ma, F.Flow2(f, fromEither))
} }
func ChainEitherK[A, E, B, HKTEA, HKTEB any](
mchain func(func(A) HKTEB) func(HKTEA) HKTEB,
fromEither func(ET.Either[E, B]) HKTEB,
f func(A) ET.Either[E, B]) func(HKTEA) HKTEB {
return mchain(F.Flow2(f, fromEither))
}
func ChainOptionK[A, E, B, HKTEA, HKTEB any]( func ChainOptionK[A, E, B, HKTEA, HKTEB any](
mchain func(HKTEA, func(A) HKTEB) HKTEB, mchain func(HKTEA, func(A) HKTEB) HKTEB,
fromEither func(ET.Either[E, B]) HKTEB, fromEither func(ET.Either[E, B]) HKTEB,
@@ -78,8 +85,8 @@ func MonadChainFirstEitherK[A, E, B, HKTEA, HKTEB any](
} }
func ChainFirstEitherK[A, E, B, HKTEA, HKTEB any]( func ChainFirstEitherK[A, E, B, HKTEA, HKTEB any](
mchain func(HKTEA, func(A) HKTEA) HKTEA, mchain func(func(A) HKTEA) func(HKTEA) HKTEA,
mmap func(HKTEB, func(B) A) HKTEA, mmap func(func(B) A) func(HKTEB) HKTEA,
fromEither func(ET.Either[E, B]) HKTEB, fromEither func(ET.Either[E, B]) HKTEB,
f func(A) ET.Either[E, B]) func(HKTEA) HKTEA { f func(A) ET.Either[E, B]) func(HKTEA) HKTEA {
return C.ChainFirst(mchain, mmap, F.Flow2(f, fromEither)) return C.ChainFirst(mchain, mmap, F.Flow2(f, fromEither))

View File

@@ -30,8 +30,8 @@ func MonadChainFirstIOK[A, B, HKTA, HKTB any, GIOB ~func() B](
} }
func ChainFirstIOK[A, B, HKTA, HKTB any, GIOB ~func() B]( func ChainFirstIOK[A, B, HKTA, HKTB any, GIOB ~func() B](
mchain func(HKTA, func(A) HKTA) HKTA, mchain func(func(A) HKTA) func(HKTA) HKTA,
mmap func(HKTB, func(B) A) HKTA, mmap func(func(B) A) func(HKTB) HKTA,
fromio func(GIOB) HKTB, fromio func(GIOB) HKTB,
f func(A) GIOB) func(HKTA) HKTA { f func(A) GIOB) func(HKTA) HKTA {
// chain // chain

View File

@@ -31,8 +31,8 @@ func MonadChainFirstIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB
} }
func ChainFirstIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB any]( func ChainFirstIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB any](
mchain func(HKTA, func(A) HKTA) HKTA, mchain func(func(A) HKTA) func(HKTA) HKTA,
mmap func(HKTB, func(B) A) HKTA, mmap func(func(B) A) func(HKTB) HKTA,
fromio func(GIOB) HKTB, fromio func(GIOB) HKTB,
f func(A) GIOB) func(HKTA) HKTA { f func(A) GIOB) func(HKTA) HKTA {
// chain // chain

View File

@@ -15,23 +15,24 @@
package functor package functor
func flap[FAB ~func(A) B, A, B any](a A) func(FAB) B {
return func(f FAB) B {
return f(a)
}
}
func MonadFlap[FAB ~func(A) B, A, B, HKTFAB, HKTB any]( func MonadFlap[FAB ~func(A) B, A, B, HKTFAB, HKTB any](
fmap func(HKTFAB, func(FAB) B) HKTB, fmap func(HKTFAB, func(FAB) B) HKTB,
fab HKTFAB, fab HKTFAB,
a A, a A,
) HKTB { ) HKTB {
return fmap(fab, func(f FAB) B { return fmap(fab, flap[FAB, A, B](a))
return f(a)
})
} }
func Flap[FAB ~func(A) B, A, B, HKTFAB, HKTB any]( func Flap[FAB ~func(A) B, A, B, HKTFAB, HKTB any](
fmap func(HKTFAB, func(FAB) B) HKTB, fmap func(func(FAB) B) func(HKTFAB) HKTB,
a A, a A,
) func(HKTFAB) HKTB { ) func(HKTFAB) HKTB {
return func(fab HKTFAB) HKTB { return fmap(flap[FAB, A, B](a))
return MonadFlap(fmap, fab, a)
}
} }

View File

@@ -33,11 +33,7 @@ func Map[A, B, HKTGA, HKTGB, HKTFGA, HKTFGB any](
fmap func(func(HKTGA) HKTGB) func(HKTFGA) HKTFGB, fmap func(func(HKTGA) HKTGB) func(HKTFGA) HKTFGB,
gmap func(func(A) B) func(HKTGA) HKTGB, gmap func(func(A) B) func(HKTGA) HKTGB,
f func(A) B) func(HKTFGA) HKTFGB { f func(A) B) func(HKTFGA) HKTFGB {
return F.Pipe2( return fmap(gmap(f))
f,
gmap,
fmap,
)
} }
func MonadLet[S1, S2, B, HKTS1, HKTS2 any]( func MonadLet[S1, S2, B, HKTS1, HKTS2 any](
@@ -66,9 +62,5 @@ func LetTo[S1, S2, B, HKTS1, HKTS2 any](
key func(B) func(S1) S2, key func(B) func(S1) S2,
b B, b B,
) func(HKTS1) HKTS2 { ) func(HKTS1) HKTS2 {
return F.Pipe2( return mmap(key(b))
b,
key,
mmap,
)
} }

View File

@@ -50,13 +50,11 @@ func MonadChain[A, B, HKTFA, HKTFB any](
} }
func Chain[A, B, HKTFA, HKTFB any]( func Chain[A, B, HKTFA, HKTFB any](
fchain func(HKTFA, func(O.Option[A]) HKTFB) HKTFB, fchain func(func(O.Option[A]) HKTFB) func(HKTFA) HKTFB,
fof func(O.Option[B]) HKTFB, fof func(O.Option[B]) HKTFB,
f func(A) HKTFB) func(ma HKTFA) HKTFB { f func(A) HKTFB) func(ma HKTFA) HKTFB {
// dispatch to the even more generic implementation // dispatch to the even more generic implementation
return func(ma HKTFA) HKTFB { return fchain(O.Fold(F.Nullary2(O.None[B], fof), f))
return MonadChain(fchain, fof, ma, f)
}
} }
func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any]( func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
@@ -67,6 +65,13 @@ func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
return apply.MonadAp(fap, fmap, O.MonadAp[B, A], fab, fa) return apply.MonadAp(fap, fmap, O.MonadAp[B, A], fab, fa)
} }
func Ap[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
fap func(HKTFA) func(HKTFGAB) HKTFB,
fmap func(func(O.Option[func(A) B]) func(O.Option[A]) O.Option[B]) func(HKTFAB) HKTFGAB,
fa HKTFA) func(HKTFAB) HKTFB {
return apply.Ap(fap, fmap, O.Ap[B, A], fa)
}
func MatchE[A, HKTEA, HKTB any](mchain func(HKTEA, func(O.Option[A]) HKTB) HKTB, onNone func() HKTB, onSome func(A) HKTB) func(HKTEA) HKTB { func MatchE[A, HKTEA, HKTB any](mchain func(HKTEA, func(O.Option[A]) HKTB) HKTB, onNone func() HKTB, onSome func(A) HKTB) func(HKTEA) HKTB {
return F.Bind2nd(mchain, O.Fold(onNone, onSome)) return F.Bind2nd(mchain, O.Fold(onNone, onSome))
} }
@@ -86,6 +91,14 @@ func MonadChainOptionK[A, B, HKTA, HKTB any](
return MonadChain(fchain, fof, ma, FromOptionK(fof, f)) return MonadChain(fchain, fof, ma, FromOptionK(fof, f))
} }
func ChainOptionK[A, B, HKTA, HKTB any](
fchain func(func(O.Option[A]) HKTB) func(HKTA) HKTB,
fof func(O.Option[B]) HKTB,
f func(A) O.Option[B],
) func(HKTA) HKTB {
return Chain(fchain, fof, FromOptionK(fof, f))
}
func MonadAlt[LAZY ~func() HKTFA, A, HKTFA any]( func MonadAlt[LAZY ~func() HKTFA, A, HKTFA any](
fof func(O.Option[A]) HKTFA, fof func(O.Option[A]) HKTFA,
fchain func(HKTFA, func(O.Option[A]) HKTFA) HKTFA, fchain func(HKTFA, func(O.Option[A]) HKTFA) HKTFA,
@@ -98,11 +111,9 @@ func MonadAlt[LAZY ~func() HKTFA, A, HKTFA any](
func Alt[LAZY ~func() HKTFA, A, HKTFA any]( func Alt[LAZY ~func() HKTFA, A, HKTFA any](
fof func(O.Option[A]) HKTFA, fof func(O.Option[A]) HKTFA,
fchain func(HKTFA, func(O.Option[A]) HKTFA) HKTFA, fchain func(func(O.Option[A]) HKTFA) func(HKTFA) HKTFA,
second LAZY) func(HKTFA) HKTFA { second LAZY) func(HKTFA) HKTFA {
return func(fa HKTFA) HKTFA { return fchain(O.Fold(second, F.Flow2(O.Of[A], fof)))
return MonadAlt(fof, fchain, fa, second)
}
} }

View File

@@ -53,7 +53,7 @@ func MonadOf[GA ~func() A, A any](a A) GA {
func MonadMap[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) B) GB { func MonadMap[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) B) GB {
return MakeIO[GB](func() B { return MakeIO[GB](func() B {
return F.Pipe1(fa(), f) return f(fa())
}) })
} }
@@ -66,13 +66,13 @@ func MonadMapTo[GA ~func() A, GB ~func() B, A, B any](fa GA, b B) GB {
} }
func MapTo[GA ~func() A, GB ~func() B, A, B any](b B) func(GA) GB { func MapTo[GA ~func() A, GB ~func() B, A, B any](b B) func(GA) GB {
return F.Bind2nd(MonadMapTo[GA, GB, A, B], b) return Map[GA, GB](F.Constant1[A](b))
} }
// MonadChain composes computations in sequence, using the return value of one computation to determine the next computation. // MonadChain composes computations in sequence, using the return value of one computation to determine the next computation.
func MonadChain[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) GB) GB { func MonadChain[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) GB) GB {
return MakeIO[GB](func() B { return MakeIO[GB](func() B {
return F.Pipe1(fa(), f)() return f(fa())()
}) })
} }
@@ -88,7 +88,7 @@ func MonadChainTo[GA ~func() A, GB ~func() B, A, B any](fa GA, fb GB) GB {
// ChainTo composes computations in sequence, ignoring the return value of the first computation // ChainTo composes computations in sequence, ignoring the return value of the first computation
func ChainTo[GA ~func() A, GB ~func() B, A, B any](fb GB) func(GA) GB { func ChainTo[GA ~func() A, GB ~func() B, A, B any](fb GB) func(GA) GB {
return F.Bind2nd(MonadChainTo[GA, GB, A, B], fb) return Chain[GA, GB](F.Constant1[A](fb))
} }
// MonadChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and // MonadChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and
@@ -100,7 +100,11 @@ func MonadChainFirst[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) GB)
// ChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and // ChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and
// keeping only the result of the first. // keeping only the result of the first.
func ChainFirst[GA ~func() A, GB ~func() B, A, B any](f func(A) GB) func(GA) GA { func ChainFirst[GA ~func() A, GB ~func() B, A, B any](f func(A) GB) func(GA) GA {
return C.ChainFirst(MonadChain[GA, GA, A, A], MonadMap[GB, GA, B, A], f) return C.ChainFirst(
Chain[GA, GA, A, A],
Map[GB, GA, B, A],
f,
)
} }
func ApSeq[GB ~func() B, GAB ~func() func(A) B, GA ~func() A, B, A any](ma GA) func(GAB) GB { func ApSeq[GB ~func() B, GAB ~func() func(A) B, GA ~func() A, B, A any](ma GA) func(GAB) GB {
@@ -174,7 +178,7 @@ func MonadFlap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](fab GFA
} }
func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(GFAB) GB { func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(GFAB) GB {
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a) return FC.Flap(Map[GFAB, GB, FAB, B], a)
} }
// WithTime returns an operation that measures the start and end timestamp of the operation // WithTime returns an operation that measures the start and end timestamp of the operation

View File

@@ -87,7 +87,7 @@ func MonadMap[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B an
} }
func Map[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) B) func(GA) GB { func Map[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) B) func(GA) GB {
return F.Bind2nd(MonadMap[GA, GB, E, A, B], f) return eithert.Map(IO.Map[GA, GB, ET.Either[E, A], ET.Either[E, B]], f)
} }
func MonadMapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, b B) GB { func MonadMapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, b B) GB {
@@ -95,7 +95,7 @@ func MonadMapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B
} }
func MapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](b B) func(GA) GB { func MapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](b B) func(GA) GB {
return F.Bind2nd(MonadMapTo[GA, GB, E, A, B], b) return Map[GA, GB](F.Constant1[A](b))
} }
func MonadChain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, f func(A) GB) GB { func MonadChain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, f func(A) GB) GB {
@@ -103,7 +103,7 @@ func MonadChain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B
} }
func Chain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GB { func Chain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GB {
return F.Bind2nd(MonadChain[GA, GB, E, A, B], f) return eithert.Chain(IO.Chain[GA, GB, ET.Either[E, A], ET.Either[E, B]], IO.Of[GB, ET.Either[E, B]], f)
} }
func MonadChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, fb GB) GB { func MonadChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, fb GB) GB {
@@ -111,7 +111,7 @@ func MonadChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A,
} }
func ChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fb GB) func(GA) GB { func ChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fb GB) func(GA) GB {
return F.Bind2nd(MonadChainTo[GA, GB, E, A, B], fb) return Chain[GA, GB, E, A, B](F.Constant1[A](fb))
} }
func MonadChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](ma GA, f func(A) ET.Either[E, B]) GB { func MonadChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](ma GA, f func(A) ET.Either[E, B]) GB {
@@ -141,7 +141,11 @@ func ChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func()
} }
func ChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GB { func ChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GB {
return F.Bind2nd(MonadChainEitherK[GA, GB, E, A, B], f) return FE.ChainEitherK(
Chain[GA, GB, E, A, B],
FromEither[GB, E, B],
f,
)
} }
func MonadAp[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](mab GAB, ma GA) GB { func MonadAp[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](mab GAB, ma GA) GB {
@@ -223,7 +227,7 @@ func MonadBiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2
// BiMap maps a pair of functions over the two type arguments of the bifunctor. // BiMap maps a pair of functions over the two type arguments of the bifunctor.
func BiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB { func BiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB {
return eithert.BiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], f, g) return eithert.BiMap(IO.Map[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], f, g)
} }
// Fold convers an IOEither into an IO // Fold convers an IOEither into an IO
@@ -253,8 +257,8 @@ func MonadChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E,
// ChainFirst runs the monad returned by the function but returns the result of the original monad // ChainFirst runs the monad returned by the function but returns the result of the original monad
func ChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GA { func ChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GA {
return C.ChainFirst( return C.ChainFirst(
MonadChain[GA, GA, E, A, A], Chain[GA, GA, E, A, A],
MonadMap[GB, GA, E, B, A], Map[GB, GA, E, B, A],
f, f,
) )
} }
@@ -273,8 +277,8 @@ func MonadChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any]
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad // ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
func ChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](f func(A) GIOB) func(GA) GA { func ChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](f func(A) GIOB) func(GA) GA {
return FI.ChainFirstIOK( return FI.ChainFirstIOK(
MonadChain[GA, GA, E, A, A], Chain[GA, GA, E, A, A],
MonadMap[func() ET.Either[E, B], GA, E, B, A], Map[func() ET.Either[E, B], GA, E, B, A],
FromIO[func() ET.Either[E, B], GIOB, E, B], FromIO[func() ET.Either[E, B], GIOB, E, B],
f, f,
) )
@@ -294,8 +298,8 @@ func MonadChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](first GA, f
// ChainFirstEitherK runs the monad returned by the function but returns the result of the original monad // ChainFirstEitherK runs the monad returned by the function but returns the result of the original monad
func ChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GA { func ChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GA {
return FE.ChainFirstEitherK( return FE.ChainFirstEitherK(
MonadChain[GA, GA, E, A, A], Chain[GA, GA, E, A, A],
MonadMap[func() ET.Either[E, B], GA, E, B, A], Map[func() ET.Either[E, B], GA, E, B, A],
FromEither[func() ET.Either[E, B], E, B], FromEither[func() ET.Either[E, B], E, B],
f, f,
) )
@@ -339,7 +343,7 @@ func MonadFlap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B]
} }
func Flap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](a A) func(GEAB) GEB { func Flap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](a A) func(GEAB) GEB {
return FC.Flap(MonadMap[GEAB, GEB], a) return FC.Flap(Map[GEAB, GEB], a)
} }
func ToIOOption[GA ~func() O.Option[A], GEA ~func() ET.Either[E, A], E, A any](ioe GEA) GA { func ToIOOption[GA ~func() O.Option[A], GEA ~func() ET.Either[E, A], E, A any](ioe GEA) GA {

View File

@@ -90,8 +90,8 @@ func MonadChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](m
// ChainFirst runs the monad returned by the function but returns the result of the original monad // ChainFirst runs the monad returned by the function but returns the result of the original monad
func ChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GA { func ChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GA {
return C.ChainFirst( return C.ChainFirst(
MonadChain[GA, GA, A, A], Chain[GA, GA, A, A],
MonadMap[GB, GA, B, A], Map[GB, GA, B, A],
f, f,
) )
} }
@@ -110,15 +110,15 @@ func MonadChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](first
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad // ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
func ChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](f func(A) GIOB) func(GA) GA { func ChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](f func(A) GIOB) func(GA) GA {
return FI.ChainFirstIOK( return FI.ChainFirstIOK(
MonadChain[GA, GA, A, A], Chain[GA, GA, A, A],
MonadMap[func() O.Option[B], GA, B, A], Map[func() O.Option[B], GA, B, A],
FromIO[func() O.Option[B], GIOB, B], FromIO[func() O.Option[B], GIOB, B],
f, f,
) )
} }
func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB { func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB {
return optiont.Chain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], f) return optiont.Chain(IO.Chain[GA, GB, O.Option[A], O.Option[B]], IO.Of[GB, O.Option[B]], f)
} }
func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB { func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB {
@@ -131,7 +131,11 @@ func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any]
} }
func ChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) O.Option[B]) func(GA) GB { func ChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) O.Option[B]) func(GA) GB {
return F.Bind2nd(MonadChainOptionK[GA, GB, A, B], f) return optiont.ChainOptionK(
IO.Chain[GA, GB, O.Option[A], O.Option[B]],
FromOption[GB, B],
f,
)
} }
func MonadChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](ma GA, f func(A) GR) GB { func MonadChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](ma GA, f func(A) GR) GB {
@@ -159,7 +163,10 @@ func MonadAp[GB ~func() O.Option[B], GAB ~func() O.Option[func(A) B], GA ~func()
} }
func Ap[GB ~func() O.Option[B], GAB ~func() O.Option[func(A) B], GA ~func() O.Option[A], A, B any](ma GA) func(GAB) GB { func Ap[GB ~func() O.Option[B], GAB ~func() O.Option[func(A) B], GA ~func() O.Option[A], A, B any](ma GA) func(GAB) GB {
return F.Bind2nd(MonadAp[GB, GAB, GA, A, B], ma) return optiont.Ap(
IO.Ap[GB, func() func(O.Option[A]) O.Option[B], GA, O.Option[B], O.Option[A]],
IO.Map[GAB, func() func(O.Option[A]) O.Option[B], O.Option[func(A) B], func(O.Option[A]) O.Option[B]],
ma)
} }
func Flatten[GA ~func() O.Option[A], GAA ~func() O.Option[GA], A any](mma GAA) GA { func Flatten[GA ~func() O.Option[A], GAA ~func() O.Option[GA], A any](mma GAA) GA {
@@ -236,7 +243,7 @@ func Defer[GA ~func() O.Option[A], A any](gen func() GA) GA {
func MonadAlt[LAZY ~func() GIOA, GIOA ~func() O.Option[A], A any](first GIOA, second LAZY) GIOA { func MonadAlt[LAZY ~func() GIOA, GIOA ~func() O.Option[A], A any](first GIOA, second LAZY) GIOA {
return optiont.MonadAlt( return optiont.MonadAlt(
IO.Of[GIOA], IO.MonadOf[GIOA],
IO.MonadChain[GIOA, GIOA], IO.MonadChain[GIOA, GIOA],
first, first,
@@ -245,5 +252,10 @@ func MonadAlt[LAZY ~func() GIOA, GIOA ~func() O.Option[A], A any](first GIOA, se
} }
func Alt[LAZY ~func() GIOA, GIOA ~func() O.Option[A], A any](second LAZY) func(GIOA) GIOA { func Alt[LAZY ~func() GIOA, GIOA ~func() O.Option[A], A any](second LAZY) func(GIOA) GIOA {
return F.Bind2nd(MonadAlt[LAZY], second) return optiont.Alt(
IO.Of[GIOA],
IO.Chain[GIOA, GIOA],
second,
)
} }

View File

@@ -156,5 +156,5 @@ func MonadFlap[B, A any](fab Option[func(A) B], a A) Option[B] {
} }
func Flap[B, A any](a A) func(Option[func(A) B]) Option[B] { func Flap[B, A any](a A) func(Option[func(A) B]) Option[B] {
return F.Bind2nd(MonadFlap[B, A], a) return FC.Flap(Map[func(A) B, B], a)
} }

View File

@@ -127,5 +127,5 @@ func MonadFlap[GAB ~func(R) func(A) B, GB ~func(R) B, R, A, B any](fab GAB, a A)
} }
func Flap[GAB ~func(R) func(A) B, GB ~func(R) B, R, A, B any](a A) func(GAB) GB { func Flap[GAB ~func(R) func(A) B, GB ~func(R) B, R, A, B any](a A) func(GAB) GB {
return FC.Flap(MonadMap[GAB, GB], a) return FC.Flap(Map[GAB, GB], a)
} }

View File

@@ -143,7 +143,7 @@ func MonadBiMap[GA ~func(E) ET.Either[E1, A], GB ~func(E) ET.Either[E2, B], E, E
// BiMap maps a pair of functions over the two type arguments of the bifunctor. // BiMap maps a pair of functions over the two type arguments of the bifunctor.
func BiMap[GA ~func(E) ET.Either[E1, A], GB ~func(E) ET.Either[E2, B], E, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB { func BiMap[GA ~func(E) ET.Either[E1, A], GB ~func(E) ET.Either[E2, B], E, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB {
return eithert.BiMap(R.MonadMap[GA, GB, E, ET.Either[E1, A], ET.Either[E2, B]], f, g) return eithert.BiMap(R.Map[GA, GB, E, ET.Either[E1, A], ET.Either[E2, B]], f, g)
} }
// Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s // Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s
@@ -162,7 +162,7 @@ func MonadFlap[GEFAB ~func(E) ET.Either[L, func(A) B], GEB ~func(E) ET.Either[L,
} }
func Flap[GEFAB ~func(E) ET.Either[L, func(A) B], GEB ~func(E) ET.Either[L, B], L, E, A, B any](a A) func(GEFAB) GEB { func Flap[GEFAB ~func(E) ET.Either[L, func(A) B], GEB ~func(E) ET.Either[L, B], L, E, A, B any](a A) func(GEFAB) GEB {
return FC.Flap(MonadMap[GEFAB, GEB], a) return FC.Flap(Map[GEFAB, GEB], a)
} }
func MonadMapLeft[GA1 ~func(C) ET.Either[E1, A], GA2 ~func(C) ET.Either[E2, A], C, E1, E2, A any](fa GA1, f func(E1) E2) GA2 { func MonadMapLeft[GA1 ~func(C) ET.Either[E1, A], GA2 ~func(C) ET.Either[E2, A], C, E1, E2, A any](fa GA1, f func(E1) E2) GA2 {

View File

@@ -114,8 +114,8 @@ func MonadChainFirstIOK[GEA ~func(E) GIOA, GEB ~func(E) GIOB, GIOA ~func() A, GI
func ChainFirstIOK[GEA ~func(E) GIOA, GEB ~func(E) GIOB, GIOA ~func() A, GIOB ~func() B, E, A, B any](f func(A) GIOB) func(GEA) GEA { func ChainFirstIOK[GEA ~func(E) GIOA, GEB ~func(E) GIOB, GIOA ~func() A, GIOB ~func() B, E, A, B any](f func(A) GIOB) func(GEA) GEA {
return FIO.ChainFirstIOK( return FIO.ChainFirstIOK(
MonadChain[GEA, GEA], Chain[GEA, GEA],
MonadMap[GEB, GEA], Map[GEB, GEA],
FromIO[GEB], FromIO[GEB],
f, f,
) )
@@ -162,5 +162,5 @@ func MonadFlap[GEFAB ~func(E) GIOFAB, GEB ~func(E) GIOB, GIOFAB ~func() func(A)
} }
func Flap[GEFAB ~func(E) GIOFAB, GEB ~func(E) GIOB, GIOFAB ~func() func(A) B, GIOB ~func() B, E, A, B any](a A) func(GEFAB) GEB { func Flap[GEFAB ~func(E) GIOFAB, GEB ~func(E) GIOB, GIOFAB ~func() func(A) B, GIOB ~func() B, E, A, B any](a A) func(GEFAB) GEB {
return FC.Flap(MonadMap[GEFAB, GEB], a) return FC.Flap(Map[GEFAB, GEB], a)
} }

View File

@@ -405,7 +405,7 @@ func MonadBiMap[GA ~func(R) GE1A, GB ~func(R) GE2B, GE1A ~func() ET.Either[E1, A
// BiMap maps a pair of functions over the two type arguments of the bifunctor. // BiMap maps a pair of functions over the two type arguments of the bifunctor.
func BiMap[GA ~func(R) GE1A, GB ~func(R) GE2B, GE1A ~func() ET.Either[E1, A], GE2B ~func() ET.Either[E2, B], R, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB { func BiMap[GA ~func(R) GE1A, GB ~func(R) GE2B, GE1A ~func() ET.Either[E1, A], GE2B ~func() ET.Either[E2, B], R, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB {
return eithert.BiMap(G.MonadMap[GA, GB, GE1A, GE2B, R, ET.Either[E1, A], ET.Either[E2, B]], f, g) return eithert.BiMap(G.Map[GA, GB, GE1A, GE2B, R, ET.Either[E1, A], ET.Either[E2, B]], f, g)
} }
// Swap changes the order of type parameters // Swap changes the order of type parameters
@@ -438,7 +438,7 @@ func MonadFlap[GREAB ~func(R) GEAB, GREB ~func(R) GEB, GEAB ~func() ET.Either[E,
} }
func Flap[GREAB ~func(R) GEAB, GREB ~func(R) GEB, GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], R, E, B, A any](a A) func(GREAB) GREB { func Flap[GREAB ~func(R) GEAB, GREB ~func(R) GEB, GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], R, E, B, A any](a A) func(GREAB) GREB {
return FC.Flap(MonadMap[GREAB, GREB], a) return FC.Flap(Map[GREAB, GREB], a)
} }
func MonadMapLeft[GREA1 ~func(R) GEA1, GREA2 ~func(R) GEA2, GEA1 ~func() ET.Either[E1, A], GEA2 ~func() ET.Either[E2, A], R, E1, E2, A any](fa GREA1, f func(E1) E2) GREA2 { func MonadMapLeft[GREA1 ~func(R) GEA1, GREA2 ~func(R) GEA2, GEA1 ~func() ET.Either[E1, A], GEA2 ~func() ET.Either[E2, A], R, E1, E2, A any](fa GREA1, f func(E1) E2) GREA2 {

View File

@@ -598,7 +598,7 @@ func MonadFlap[GFAB ~map[K]func(A) B, GB ~map[K]B, K comparable, A, B any](fab G
} }
func Flap[GFAB ~map[K]func(A) B, GB ~map[K]B, K comparable, A, B any](a A) func(GFAB) GB { func Flap[GFAB ~map[K]func(A) B, GB ~map[K]B, K comparable, A, B any](a A) func(GFAB) GB {
return FC.Flap(MonadMap[GFAB, GB], a) return FC.Flap(Map[GFAB, GB], a)
} }
func Copy[M ~map[K]V, K comparable, V any](m M) M { func Copy[M ~map[K]V, K comparable, V any](m M) M {

View File

@@ -0,0 +1,75 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package reader implements the example in [https://dev.to/gcanti/getting-started-with-fp-ts-reader-1ie5]
package example1
import (
"fmt"
F "github.com/IBM/fp-go/function"
N "github.com/IBM/fp-go/number"
I "github.com/IBM/fp-go/number/integer"
"github.com/IBM/fp-go/ord"
R "github.com/IBM/fp-go/reader"
S "github.com/IBM/fp-go/string"
)
type (
I18n struct {
True string
False string
}
Dependencies struct {
I18n I18n
}
)
var (
// g: func(int) R.Reader[*Dependencies, string], note how the implementation does not depend on the dependencies
g = F.Flow2(
ord.Gt(I.Ord)(2),
f,
)
// h: func(string) R.Reader[*Dependencies, string], note how the implementation does not depend on the dependencies
h = F.Flow3(
S.Size,
N.Add(1),
g,
)
)
func f(b bool) R.Reader[*Dependencies, string] {
return func(deps *Dependencies) string {
if b {
return deps.I18n.True
}
return deps.I18n.False
}
}
func ExampleReader() {
deps := Dependencies{I18n: I18n{True: "vero", False: "falso"}}
fmt.Println(h("foo")(&deps))
fmt.Println(h("a")(&deps))
// Output:
// vero
// falso
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package reader implements the example in [https://dev.to/gcanti/getting-started-with-fp-ts-reader-1ie5]
package example2
import (
"fmt"
F "github.com/IBM/fp-go/function"
ID "github.com/IBM/fp-go/identity"
N "github.com/IBM/fp-go/number"
I "github.com/IBM/fp-go/number/integer"
"github.com/IBM/fp-go/ord"
R "github.com/IBM/fp-go/reader"
S "github.com/IBM/fp-go/string"
)
type (
I18n struct {
True string
False string
}
Dependencies struct {
I18n I18n
LowerBound int
}
)
var (
// h: func(string) R.Reader[*Dependencies, string], note how the implementation does not depend on the dependencies
h = F.Flow3(
S.Size,
N.Add(1),
g,
)
)
func getLowerBound(deps *Dependencies) int {
return deps.LowerBound
}
func g(n int) R.Reader[*Dependencies, string] {
return F.Pipe1(
R.Ask[*Dependencies](),
R.Chain(F.Flow4(
getLowerBound,
ord.Gt(I.Ord),
ID.Flap[bool](n),
f,
)),
)
}
func f(b bool) R.Reader[*Dependencies, string] {
return func(deps *Dependencies) string {
if b {
return deps.I18n.True
}
return deps.I18n.False
}
}
func ExampleReader() {
deps1 := Dependencies{I18n: I18n{True: "vero", False: "falso"}, LowerBound: 2}
hFoo := h("foo")
hA := h("a")
fmt.Println(hFoo(&deps1))
fmt.Println(hA(&deps1))
deps2 := Dependencies{I18n: I18n{True: "vero", False: "falso"}, LowerBound: 4}
fmt.Println(hFoo(&deps2))
fmt.Println(hA(&deps2))
// Output:
// vero
// falso
// falso
// falso
}

View File

@@ -17,7 +17,6 @@ package writer
import ( import (
M "github.com/IBM/fp-go/monoid" M "github.com/IBM/fp-go/monoid"
S "github.com/IBM/fp-go/semigroup"
G "github.com/IBM/fp-go/writer/generic" G "github.com/IBM/fp-go/writer/generic"
) )
@@ -27,11 +26,11 @@ func Do[S, W any](m M.Monoid[W]) func(S) Writer[W, S] {
} }
// Bind attaches the result of a computation to a context [S1] to produce a context [S2] // Bind attaches the result of a computation to a context [S1] to produce a context [S2]
func Bind[S1, S2, T, W any](s S.Semigroup[W]) func( func Bind[S1, S2, T, W any](
setter func(T) func(S1) S2, setter func(T) func(S1) S2,
f func(S1) Writer[W, T], f func(S1) Writer[W, T],
) func(Writer[W, S1]) Writer[W, S2] { ) func(Writer[W, S1]) Writer[W, S2] {
return G.Bind[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](s) return G.Bind[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](setter, f)
} }
// Let attaches the result of a computation to a context [S1] to produce a context [S2] // Let attaches the result of a computation to a context [S1] to produce a context [S2]
@@ -58,9 +57,9 @@ func BindTo[W, S1, T any](
} }
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently // ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
func ApS[S1, S2, T, W any](s S.Semigroup[W]) func( func ApS[S1, S2, T, W any](
setter func(T) func(S1) S2, setter func(T) func(S1) S2,
fa Writer[W, T], fa Writer[W, T],
) func(Writer[W, S1]) Writer[W, S2] { ) func(Writer[W, S1]) Writer[W, S2] {
return G.ApS[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](s) return G.ApS[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](setter, fa)
} }

View File

@@ -19,6 +19,7 @@ import (
"testing" "testing"
A "github.com/IBM/fp-go/array" A "github.com/IBM/fp-go/array"
EQ "github.com/IBM/fp-go/eq"
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/internal/utils" "github.com/IBM/fp-go/internal/utils"
M "github.com/IBM/fp-go/monoid" M "github.com/IBM/fp-go/monoid"
@@ -28,6 +29,8 @@ import (
var ( var (
monoid = A.Monoid[string]() monoid = A.Monoid[string]()
sg = M.ToSemigroup(monoid) sg = M.ToSemigroup(monoid)
eq = Eq(A.Eq[string](EQ.FromStrictEquals[string]()), EQ.FromStrictEquals[string]())
) )
func getLastName(s utils.Initial) Writer[[]string, string] { func getLastName(s utils.Initial) Writer[[]string, string] {
@@ -42,22 +45,22 @@ func TestBind(t *testing.T) {
res := F.Pipe3( res := F.Pipe3(
Do[utils.Initial](monoid)(utils.Empty), Do[utils.Initial](monoid)(utils.Empty),
Bind[utils.Initial, utils.WithLastName, string](sg)(utils.SetLastName, getLastName), Bind(utils.SetLastName, getLastName),
Bind[utils.WithLastName, utils.WithGivenName, string](sg)(utils.SetGivenName, getGivenName), Bind(utils.SetGivenName, getGivenName),
Map[[]string](utils.GetFullName), Map[[]string](utils.GetFullName),
) )
assert.Equal(t, res(), Of[string](monoid)("John Doe")()) assert.True(t, eq.Equals(res, Of[string](monoid)("John Doe")))
} }
func TestApS(t *testing.T) { func TestApS(t *testing.T) {
res := F.Pipe3( res := F.Pipe3(
Do[utils.Initial](monoid)(utils.Empty), Do[utils.Initial](monoid)(utils.Empty),
ApS[utils.Initial, utils.WithLastName, string](sg)(utils.SetLastName, Of[string](monoid)("Doe")), ApS(utils.SetLastName, Of[string](monoid)("Doe")),
ApS[utils.WithLastName, utils.WithGivenName, string](sg)(utils.SetGivenName, Of[string](monoid)("John")), ApS(utils.SetGivenName, Of[string](monoid)("John")),
Map[[]string](utils.GetFullName), Map[[]string](utils.GetFullName),
) )
assert.Equal(t, res(), Of[string](monoid)("John Doe")()) assert.True(t, eq.Equals(res, Of[string](monoid)("John Doe")))
} }

View File

@@ -20,36 +20,30 @@ import (
C "github.com/IBM/fp-go/internal/chain" C "github.com/IBM/fp-go/internal/chain"
F "github.com/IBM/fp-go/internal/functor" F "github.com/IBM/fp-go/internal/functor"
M "github.com/IBM/fp-go/monoid" M "github.com/IBM/fp-go/monoid"
S "github.com/IBM/fp-go/semigroup" SG "github.com/IBM/fp-go/semigroup"
T "github.com/IBM/fp-go/tuple" T "github.com/IBM/fp-go/tuple"
) )
// Bind creates an empty context of type [S] to be used with the [Bind] operation // Bind creates an empty context of type [S] to be used with the [Bind] operation
func Do[GS ~func() T.Tuple2[S, W], W, S any](m M.Monoid[W]) func(S) GS { func Do[GS ~func() T.Tuple3[S, W, SG.Semigroup[W]], W, S any](m M.Monoid[W]) func(S) GS {
return Of[GS, W, S](m) return Of[GS, W, S](m)
} }
// Bind attaches the result of a computation to a context [S1] to produce a context [S2] // Bind attaches the result of a computation to a context [S1] to produce a context [S2]
func Bind[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], GT ~func() T.Tuple2[A, W], W, S1, S2, A any](s S.Semigroup[W]) func( func Bind[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, S2, A any](
setter func(A) func(S1) S2, setter func(A) func(S1) S2,
f func(S1) GT, f func(S1) GT,
) func(GS1) GS2 { ) func(GS1) GS2 {
ch := Chain[GS2, GS1, func(S1) GS2, W, S1, S2](s) return C.Bind(
return func( Chain[GS2, GS1, func(S1) GS2, W, S1, S2],
setter func(A) func(S1) S2, Map[GS2, GT, func(A) S2, W, A, S2],
f func(S1) GT, setter,
) func(GS1) GS2 { f,
return C.Bind( )
ch,
Map[GS2, GT, func(A) S2, W, A, S2],
setter,
f,
)
}
} }
// Let attaches the result of a computation to a context [S1] to produce a context [S2] // Let attaches the result of a computation to a context [S1] to produce a context [S2]
func Let[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], W, S1, S2, A any]( func Let[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], W, S1, S2, A any](
key func(A) func(S1) S2, key func(A) func(S1) S2,
f func(S1) A, f func(S1) A,
) func(GS1) GS2 { ) func(GS1) GS2 {
@@ -61,7 +55,7 @@ func Let[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], W, S1, S2, A
} }
// LetTo attaches the a value to a context [S1] to produce a context [S2] // LetTo attaches the a value to a context [S1] to produce a context [S2]
func LetTo[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], W, S1, S2, B any]( func LetTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], W, S1, S2, B any](
key func(B) func(S1) S2, key func(B) func(S1) S2,
b B, b B,
) func(GS1) GS2 { ) func(GS1) GS2 {
@@ -73,7 +67,7 @@ func LetTo[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], W, S1, S2,
} }
// BindTo initializes a new state [S1] from a value [T] // BindTo initializes a new state [S1] from a value [T]
func BindTo[GS1 ~func() T.Tuple2[S1, W], GT ~func() T.Tuple2[A, W], W, S1, A any]( func BindTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, A any](
setter func(A) S1, setter func(A) S1,
) func(GT) GS1 { ) func(GT) GS1 {
return C.BindTo( return C.BindTo(
@@ -83,20 +77,14 @@ func BindTo[GS1 ~func() T.Tuple2[S1, W], GT ~func() T.Tuple2[A, W], W, S1, A any
} }
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently // ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
func ApS[GS1 ~func() T.Tuple2[S1, W], GS2 ~func() T.Tuple2[S2, W], GT ~func() T.Tuple2[A, W], W, S1, S2, A any](s S.Semigroup[W]) func( func ApS[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, S2, A any](
setter func(A) func(S1) S2, setter func(A) func(S1) S2,
fa GT, fa GT,
) func(GS1) GS2 { ) func(GS1) GS2 {
ap := Ap[GS2, func() T.Tuple2[func(A) S2, W], GT, W, A, S2](s) return apply.ApS(
return func( Ap[GS2, func() T.Tuple3[func(A) S2, W, SG.Semigroup[W]], GT, W, A, S2],
setter func(A) func(S1) S2, Map[func() T.Tuple3[func(A) S2, W, SG.Semigroup[W]], GS1, func(S1) func(A) S2],
fa GT, setter,
) func(GS1) GS2 { fa,
return apply.ApS( )
ap,
Map[func() T.Tuple2[func(A) S2, W], GS1, func(S1) func(A) S2],
setter,
fa,
)
}
} }

View File

@@ -17,11 +17,12 @@ package generic
import ( import (
EQ "github.com/IBM/fp-go/eq" EQ "github.com/IBM/fp-go/eq"
SG "github.com/IBM/fp-go/semigroup"
T "github.com/IBM/fp-go/tuple" T "github.com/IBM/fp-go/tuple"
) )
// Constructs an equal predicate for a [Writer] // Constructs an equal predicate for a [Writer]
func Eq[GA ~func() T.Tuple2[A, W], W, A any](w EQ.Eq[W], a EQ.Eq[A]) EQ.Eq[GA] { func Eq[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](w EQ.Eq[W], a EQ.Eq[A]) EQ.Eq[GA] {
return EQ.FromEquals(func(l, r GA) bool { return EQ.FromEquals(func(l, r GA) bool {
ll := l() ll := l()
rr := r() rr := r()
@@ -31,6 +32,6 @@ func Eq[GA ~func() T.Tuple2[A, W], W, A any](w EQ.Eq[W], a EQ.Eq[A]) EQ.Eq[GA] {
} }
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function // FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[GA ~func() T.Tuple2[A, W], W, A comparable]() EQ.Eq[GA] { func FromStrictEquals[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A comparable]() EQ.Eq[GA] {
return Eq[GA](EQ.FromStrictEquals[W](), EQ.FromStrictEquals[A]()) return Eq[GA](EQ.FromStrictEquals[W](), EQ.FromStrictEquals[A]())
} }

View File

@@ -17,121 +17,137 @@ package generic
import ( import (
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
C "github.com/IBM/fp-go/internal/chain"
FC "github.com/IBM/fp-go/internal/functor"
IO "github.com/IBM/fp-go/io/generic" IO "github.com/IBM/fp-go/io/generic"
M "github.com/IBM/fp-go/monoid" M "github.com/IBM/fp-go/monoid"
S "github.com/IBM/fp-go/semigroup" SG "github.com/IBM/fp-go/semigroup"
T "github.com/IBM/fp-go/tuple" T "github.com/IBM/fp-go/tuple"
) )
func Of[GA ~func() T.Tuple2[A, W], W, A any](m M.Monoid[W]) func(A) GA { func Tell[GA ~func() T.Tuple3[any, W, SG.Semigroup[W]], W any](s SG.Semigroup[W]) func(W) GA {
return F.Flow2( return F.Flow2(
F.Bind2nd(T.MakeTuple2[A, W], m.Empty()), F.Bind13of3(T.MakeTuple3[any, W, SG.Semigroup[W]])(nil, s),
IO.Of[GA],
)
}
func Of[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](m M.Monoid[W]) func(A) GA {
return F.Flow2(
F.Bind23of3(T.MakeTuple3[A, W, SG.Semigroup[W]])(m.Empty(), M.ToSemigroup(m)),
IO.Of[GA], IO.Of[GA],
) )
} }
// Listen modifies the result to include the changes to the accumulator // Listen modifies the result to include the changes to the accumulator
func Listen[GA ~func() T.Tuple2[A, W], GTA ~func() T.Tuple2[T.Tuple2[A, W], W], W, A any](fa GA) GTA { func Listen[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GTA ~func() T.Tuple3[T.Tuple2[A, W], W, SG.Semigroup[W]], W, A any](fa GA) GTA {
return func() T.Tuple2[T.Tuple2[A, W], W] { return func() T.Tuple3[T.Tuple2[A, W], W, SG.Semigroup[W]] {
t := fa() t := fa()
return T.MakeTuple2(T.MakeTuple2(t.F1, t.F2), t.F2) return T.MakeTuple3(T.MakeTuple2(t.F1, t.F2), t.F2, t.F3)
} }
} }
// Pass applies the returned function to the accumulator // Pass applies the returned function to the accumulator
func Pass[GFA ~func() T.Tuple2[T.Tuple2[A, FCT], W], GA ~func() T.Tuple2[A, W], FCT ~func(W) W, W, A any](fa GFA) GA { func Pass[GFA ~func() T.Tuple3[T.Tuple2[A, FCT], W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](fa GFA) GA {
return func() T.Tuple2[A, W] { return func() T.Tuple3[A, W, SG.Semigroup[W]] {
t := fa() t := fa()
return T.MakeTuple2(t.F1.F1, t.F1.F2(t.F2)) return T.MakeTuple3(t.F1.F1, t.F1.F2(t.F2), t.F3)
} }
} }
func MonadMap[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) B, W, A, B any](fa GA, f FCT) GB { func MonadMap[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) B, W, A, B any](fa GA, f FCT) GB {
return IO.MonadMap[GA, GB](fa, T.Map2(f, F.Identity[W])) return IO.MonadMap[GA, GB](fa, T.Map3(f, F.Identity[W], F.Identity[SG.Semigroup[W]]))
} }
func Map[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) B, W, A, B any](f FCT) func(GA) GB { func Map[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) B, W, A, B any](f FCT) func(GA) GB {
return IO.Map[GA, GB](T.Map2(f, F.Identity[W])) return IO.Map[GA, GB](T.Map3(f, F.Identity[W], F.Identity[SG.Semigroup[W]]))
} }
func MonadChain[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) GB, W, A, B any](s S.Semigroup[W]) func(GA, FCT) GB { func MonadChain[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](fa GA, f FCT) GB {
return func(fa GA, f FCT) GB { return func() T.Tuple3[B, W, SG.Semigroup[W]] {
a := fa()
b := f(a.F1)()
return func() T.Tuple2[B, W] { return T.MakeTuple3(b.F1, b.F3.Concat(a.F2, b.F2), b.F3)
a := fa()
b := f(a.F1)()
return T.MakeTuple2(b.F1, s.Concat(a.F2, b.F2))
}
} }
} }
func Chain[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) GB, W, A, B any](s S.Semigroup[W]) func(FCT) func(GA) GB { func Chain[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](f FCT) func(GA) GB {
return F.Curry2(F.Swap(MonadChain[GB, GA, FCT](s))) return F.Bind2nd(MonadChain[GB, GA, FCT, W, A, B], f)
} }
func MonadAp[GB ~func() T.Tuple2[B, W], GAB ~func() T.Tuple2[func(A) B, W], GA ~func() T.Tuple2[A, W], W, A, B any](s S.Semigroup[W]) func(GAB, GA) GB { func MonadAp[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[func(A) B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A, B any](fab GAB, fa GA) GB {
return func(fab GAB, fa GA) GB { return func() T.Tuple3[B, W, SG.Semigroup[W]] {
return func() T.Tuple2[B, W] { f := fab()
f := fab() a := fa()
a := fa()
return T.MakeTuple2(f.F1(a.F1), s.Concat(f.F2, a.F2)) return T.MakeTuple3(f.F1(a.F1), f.F3.Concat(f.F2, a.F2), f.F3)
}
} }
} }
func Ap[GB ~func() T.Tuple2[B, W], GAB ~func() T.Tuple2[func(A) B, W], GA ~func() T.Tuple2[A, W], W, A, B any](s S.Semigroup[W]) func(GA) func(GAB) GB { func Ap[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[func(A) B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A, B any](ga GA) func(GAB) GB {
return F.Curry2(F.Swap(MonadAp[GB, GAB, GA](s))) return F.Bind2nd(MonadAp[GB, GAB, GA], ga)
} }
func MonadChainFirst[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) GB, W, A, B any](s S.Semigroup[W]) func(GA, FCT) GA { func MonadChainFirst[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](ma GA, f FCT) GA {
chain := MonadChain[GA, GA, func(A) GA](s) return C.MonadChainFirst(
return func(ma GA, f FCT) GA { MonadChain[GA, GA, func(A) GA],
return chain(ma, func(a A) GA { MonadMap[GA, GB, func(B) A],
return MonadMap[GA](f(a), F.Constant1[B](a)) ma,
}) f,
} )
} }
func ChainFirst[GB ~func() T.Tuple2[B, W], GA ~func() T.Tuple2[A, W], FCT ~func(A) GB, W, A, B any](s S.Semigroup[W]) func(FCT) func(GA) GA { func ChainFirst[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](f FCT) func(GA) GA {
return F.Curry2(F.Swap(MonadChainFirst[GB, GA, FCT](s))) return C.ChainFirst(
Chain[GA, GA, func(A) GA],
Map[GA, GB, func(B) A],
f,
)
} }
func Flatten[GAA ~func() T.Tuple2[GA, W], GA ~func() T.Tuple2[A, W], W, A any](s S.Semigroup[W]) func(GAA) GA { func Flatten[GAA ~func() T.Tuple3[GA, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](mma GAA) GA {
chain := MonadChain[GA, GAA, func(GA) GA](s) return MonadChain[GA, GAA, func(GA) GA](mma, F.Identity[GA])
return func(mma GAA) GA {
return chain(mma, F.Identity[GA])
}
} }
func Execute[GA ~func() T.Tuple2[A, W], W, A any](fa GA) W { func Execute[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](fa GA) W {
return T.Second(fa()) return fa().F2
} }
func Evaluate[GA ~func() T.Tuple2[A, W], W, A any](fa GA) A { func Evaluate[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](fa GA) A {
return T.First(fa()) return fa().F1
} }
// MonadCensor modifies the final accumulator value by applying a function // MonadCensor modifies the final accumulator value by applying a function
func MonadCensor[GA ~func() T.Tuple2[A, W], FCT ~func(W) W, W, A any](fa GA, f FCT) GA { func MonadCensor[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](fa GA, f FCT) GA {
return IO.MonadMap[GA, GA](fa, T.Map2(F.Identity[A], f)) return IO.MonadMap[GA, GA](fa, T.Map3(F.Identity[A], f, F.Identity[SG.Semigroup[W]]))
} }
// Censor modifies the final accumulator value by applying a function // Censor modifies the final accumulator value by applying a function
func Censor[GA ~func() T.Tuple2[A, W], FCT ~func(W) W, W, A any](f FCT) func(GA) GA { func Censor[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](f FCT) func(GA) GA {
return IO.Map[GA, GA](T.Map2(F.Identity[A], f)) return IO.Map[GA, GA](T.Map3(F.Identity[A], f, F.Identity[SG.Semigroup[W]]))
} }
// MonadListens projects a value from modifications made to the accumulator during an action // MonadListens projects a value from modifications made to the accumulator during an action
func MonadListens[GA ~func() T.Tuple2[A, W], GAB ~func() T.Tuple2[T.Tuple2[A, B], W], FCT ~func(W) B, W, A, B any](fa GA, f FCT) GAB { func MonadListens[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]], FCT ~func(W) B, W, A, B any](fa GA, f FCT) GAB {
return func() T.Tuple2[T.Tuple2[A, B], W] { return func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]] {
a := fa() a := fa()
return T.MakeTuple2(T.MakeTuple2(a.F1, f(a.F2)), a.F2) return T.MakeTuple3(T.MakeTuple2(a.F1, f(a.F2)), a.F2, a.F3)
} }
} }
// Listens projects a value from modifications made to the accumulator during an action // Listens projects a value from modifications made to the accumulator during an action
func Listens[GA ~func() T.Tuple2[A, W], GAB ~func() T.Tuple2[T.Tuple2[A, B], W], FCT ~func(W) B, W, A, B any](f FCT) func(GA) GAB { func Listens[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]], FCT ~func(W) B, W, A, B any](f FCT) func(GA) GAB {
return F.Bind2nd(MonadListens[GA, GAB, FCT], f) return F.Bind2nd(MonadListens[GA, GAB, FCT], f)
} }
func MonadFlap[FAB ~func(A) B, GFAB ~func() T.Tuple3[FAB, W, SG.Semigroup[W]], GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], W, A, B any](fab GFAB, a A) GB {
return FC.MonadFlap(
MonadMap[GB, GFAB, func(FAB) B],
fab,
a)
}
func Flap[FAB ~func(A) B, GFAB ~func() T.Tuple3[FAB, W, SG.Semigroup[W]], GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], W, A, B any](a A) func(GFAB) GB {
return FC.Flap(Map[GB, GFAB, func(FAB) B], a)
}

View File

@@ -37,8 +37,6 @@ func AssertLaws[W, A, B, C any](t *testing.T,
bc func(B) C, bc func(B) C,
) func(a A) bool { ) func(a A) bool {
s := M.ToSemigroup(m)
return L.AssertLaws(t, return L.AssertLaws(t,
WRT.Eq(eqw, eqa), WRT.Eq(eqw, eqa),
WRT.Eq(eqw, eqb), WRT.Eq(eqw, eqb),
@@ -60,18 +58,18 @@ func AssertLaws[W, A, B, C any](t *testing.T,
WRT.MonadMap[func(func(B) C) func(func(A) B) func(A) C, W, func(B) C, func(func(A) B) func(A) C], WRT.MonadMap[func(func(B) C) func(func(A) B) func(A) C, W, func(B) C, func(func(A) B) func(A) C],
WRT.MonadChain[func(A) WRT.Writer[W, A], W, A, A](m), WRT.MonadChain[func(A) WRT.Writer[W, A], W, A, A],
WRT.MonadChain[func(A) WRT.Writer[W, B], W, A, B](m), WRT.MonadChain[func(A) WRT.Writer[W, B], W, A, B],
WRT.MonadChain[func(A) WRT.Writer[W, C], W, A, C](m), WRT.MonadChain[func(A) WRT.Writer[W, C], W, A, C],
WRT.MonadChain[func(B) WRT.Writer[W, C], W, B, C](m), WRT.MonadChain[func(B) WRT.Writer[W, C], W, B, C],
WRT.MonadAp[A, A](s), WRT.MonadAp[A, A, W],
WRT.MonadAp[B, A](s), WRT.MonadAp[B, A, W],
WRT.MonadAp[C, B](s), WRT.MonadAp[C, B, W],
WRT.MonadAp[C, A](s), WRT.MonadAp[C, A, W],
WRT.MonadAp[B, func(A) B](s), WRT.MonadAp[B, func(A) B, W],
WRT.MonadAp[func(A) C, func(A) B](s), WRT.MonadAp[func(A) C, func(A) B, W],
ab, ab,
bc, bc,

View File

@@ -24,7 +24,12 @@ import (
G "github.com/IBM/fp-go/writer/generic" G "github.com/IBM/fp-go/writer/generic"
) )
type Writer[W, A any] IO.IO[T.Tuple2[A, W]] type Writer[W, A any] IO.IO[T.Tuple3[A, W, S.Semigroup[W]]]
// Tell appends a value to the accumulator
func Tell[W any](s S.Semigroup[W]) func(W) Writer[W, any] {
return G.Tell[Writer[W, any]](s)
}
func Of[A, W any](m M.Monoid[W]) func(A) Writer[W, A] { func Of[A, W any](m M.Monoid[W]) func(A) Writer[W, A] {
return G.Of[Writer[W, A]](m) return G.Of[Writer[W, A]](m)
@@ -48,32 +53,32 @@ func Map[W any, FCT ~func(A) B, A, B any](f FCT) func(Writer[W, A]) Writer[W, B]
return G.Map[Writer[W, B], Writer[W, A]](f) return G.Map[Writer[W, B], Writer[W, A]](f)
} }
func MonadChain[FCT ~func(A) Writer[W, B], W, A, B any](s S.Semigroup[W]) func(Writer[W, A], FCT) Writer[W, B] { func MonadChain[FCT ~func(A) Writer[W, B], W, A, B any](fa Writer[W, A], fct FCT) Writer[W, B] {
return G.MonadChain[Writer[W, B], Writer[W, A], FCT](s) return G.MonadChain[Writer[W, B], Writer[W, A], FCT](fa, fct)
} }
func Chain[A, B, W any](s S.Semigroup[W]) func(func(A) Writer[W, B]) func(Writer[W, A]) Writer[W, B] { func Chain[A, B, W any](fa func(A) Writer[W, B]) func(Writer[W, A]) Writer[W, B] {
return G.Chain[Writer[W, B], Writer[W, A], func(A) Writer[W, B]](s) return G.Chain[Writer[W, B], Writer[W, A], func(A) Writer[W, B]](fa)
} }
func MonadAp[B, A, W any](s S.Semigroup[W]) func(Writer[W, func(A) B], Writer[W, A]) Writer[W, B] { func MonadAp[B, A, W any](fab Writer[W, func(A) B], fa Writer[W, A]) Writer[W, B] {
return G.MonadAp[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](s) return G.MonadAp[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](fab, fa)
} }
func Ap[B, A, W any](s S.Semigroup[W]) func(Writer[W, A]) func(Writer[W, func(A) B]) Writer[W, B] { func Ap[B, A, W any](fa Writer[W, A]) func(Writer[W, func(A) B]) Writer[W, B] {
return G.Ap[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](s) return G.Ap[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](fa)
} }
func MonadChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](s S.Semigroup[W]) func(Writer[W, A], FCT) Writer[W, A] { func MonadChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](fa Writer[W, A], fct FCT) Writer[W, A] {
return G.MonadChainFirst[Writer[W, B], Writer[W, A], FCT](s) return G.MonadChainFirst[Writer[W, B], Writer[W, A], FCT](fa, fct)
} }
func ChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](s S.Semigroup[W]) func(FCT) func(Writer[W, A]) Writer[W, A] { func ChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](fct FCT) func(Writer[W, A]) Writer[W, A] {
return G.ChainFirst[Writer[W, B], Writer[W, A], FCT](s) return G.ChainFirst[Writer[W, B], Writer[W, A], FCT](fct)
} }
func Flatten[W, A any](s S.Semigroup[W]) func(Writer[W, Writer[W, A]]) Writer[W, A] { func Flatten[W, A any](mma Writer[W, Writer[W, A]]) Writer[W, A] {
return G.Flatten[Writer[W, Writer[W, A]], Writer[W, A]](s) return G.Flatten[Writer[W, Writer[W, A]], Writer[W, A]](mma)
} }
// Execute extracts the accumulator // Execute extracts the accumulator
@@ -87,21 +92,29 @@ func Evaluate[W, A any](fa Writer[W, A]) A {
} }
// MonadCensor modifies the final accumulator value by applying a function // MonadCensor modifies the final accumulator value by applying a function
func MonadCensor[FCT ~func(W) W, W, A any](fa Writer[W, A], f FCT) Writer[W, A] { func MonadCensor[A any, FCT ~func(W) W, W any](fa Writer[W, A], f FCT) Writer[W, A] {
return G.MonadCensor[Writer[W, A]](fa, f) return G.MonadCensor[Writer[W, A]](fa, f)
} }
// Censor modifies the final accumulator value by applying a function // Censor modifies the final accumulator value by applying a function
func Censor[FCT ~func(W) W, W, A any](f FCT) func(Writer[W, A]) Writer[W, A] { func Censor[A any, FCT ~func(W) W, W any](f FCT) func(Writer[W, A]) Writer[W, A] {
return G.Censor[Writer[W, A]](f) return G.Censor[Writer[W, A]](f)
} }
// MonadListens projects a value from modifications made to the accumulator during an action // MonadListens projects a value from modifications made to the accumulator during an action
func MonadListens[FCT ~func(W) B, W, A, B any](fa Writer[W, A], f FCT) Writer[W, T.Tuple2[A, B]] { func MonadListens[A any, FCT ~func(W) B, W, B any](fa Writer[W, A], f FCT) Writer[W, T.Tuple2[A, B]] {
return G.MonadListens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](fa, f) return G.MonadListens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](fa, f)
} }
// Listens projects a value from modifications made to the accumulator during an action // Listens projects a value from modifications made to the accumulator during an action
func Listens[FCT ~func(W) B, W, A, B any](f FCT) func(Writer[W, A]) Writer[W, T.Tuple2[A, B]] { func Listens[A any, FCT ~func(W) B, W, B any](f FCT) func(Writer[W, A]) Writer[W, T.Tuple2[A, B]] {
return G.Listens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](f) return G.Listens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](f)
} }
func MonadFlap[W, B, A any](fab Writer[W, func(A) B], a A) Writer[W, B] {
return G.MonadFlap[func(A) B, Writer[W, func(A) B], Writer[W, B]](fab, a)
}
func Flap[W, B, A any](a A) func(Writer[W, func(A) B]) Writer[W, B] {
return G.Flap[func(A) B, Writer[W, func(A) B], Writer[W, B]](a)
}

View File

@@ -20,30 +20,28 @@ import (
A "github.com/IBM/fp-go/array" A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function" F "github.com/IBM/fp-go/function"
M "github.com/IBM/fp-go/monoid" S "github.com/IBM/fp-go/semigroup"
T "github.com/IBM/fp-go/tuple" T "github.com/IBM/fp-go/tuple"
) )
func doubleAndLog(data int) Writer[[]string, int] { func doubleAndLog(data int) Writer[[]string, int] {
return func() T.Tuple2[int, []string] { return func() T.Tuple3[int, []string, S.Semigroup[[]string]] {
result := data * 2 result := data * 2
return T.MakeTuple2(result, A.Of(fmt.Sprintf("Doubled %d -> %d", data, result))) return T.MakeTuple3(result, A.Of(fmt.Sprintf("Doubled %d -> %d", data, result)), sg)
} }
} }
func ExampleWriter_logging() { func ExampleWriter_logging() {
m := A.Monoid[string]() res := F.Pipe4(
s := M.ToSemigroup(m)
res := F.Pipe3(
10, 10,
Of[int](m), Of[int](monoid),
Chain[int, int](s)(doubleAndLog), Chain(doubleAndLog),
Chain[int, int](s)(doubleAndLog), Chain(doubleAndLog),
Execute[[]string, int],
) )
fmt.Println(res()) fmt.Println(res)
// Output: Tuple2[int, []string](40, [Doubled 10 -> 20 Doubled 20 -> 40]) // Output: [Doubled 10 -> 20 Doubled 20 -> 40]
} }