mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: add ioeither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -3,21 +3,21 @@ package array
|
||||
import "github.com/ibm/fp-go/internal/array"
|
||||
|
||||
func Traverse[A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func([]B) HKTRB,
|
||||
_map func(HKTRB, func([]B) func(B) []B) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func([]B) HKTRB,
|
||||
fmap func(func([]B) func(B) []B) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
f func(A) HKTB) func([]A) HKTRB {
|
||||
return array.Traverse[[]A](_of, _map, _ap, f)
|
||||
return array.Traverse[[]A](fof, fmap, fap, f)
|
||||
}
|
||||
|
||||
func MonadTraverse[A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func([]B) HKTRB,
|
||||
_map func(HKTRB, func([]B) func(B) []B) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func([]B) HKTRB,
|
||||
fmap func(func([]B) func(B) []B) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
ta []A,
|
||||
f func(A) HKTB) HKTRB {
|
||||
|
||||
return array.MonadTraverse(_of, _map, _ap, ta, f)
|
||||
return array.MonadTraverse(fof, fmap, fap, ta, f)
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@ func TestTraverse(t *testing.T) {
|
||||
|
||||
traverse := Traverse(
|
||||
O.Of[ArrayType],
|
||||
O.MonadMap[ArrayType, func(int) ArrayType],
|
||||
O.MonadAp[ArrayType, int],
|
||||
O.Map[ArrayType, func(int) ArrayType],
|
||||
O.Ap[ArrayType, int],
|
||||
|
||||
func(n int) O.Option[int] {
|
||||
if n%2 == 0 {
|
||||
|
5
bytes/bytes.go
Normal file
5
bytes/bytes.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package bytes
|
||||
|
||||
func ToString(a []byte) string {
|
||||
return string(a)
|
||||
}
|
19
bytes/monoid.go
Normal file
19
bytes/monoid.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package bytes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
A "github.com/ibm/fp-go/array"
|
||||
O "github.com/ibm/fp-go/ord"
|
||||
)
|
||||
|
||||
var (
|
||||
// monoid for byte arrays
|
||||
Monoid = A.Monoid[byte]()
|
||||
|
||||
// ConcatAll concatenates all bytes
|
||||
ConcatAll = A.ArrayConcatAll[byte]
|
||||
|
||||
// Ord implements the default ordering on bytes
|
||||
Ord = O.MakeOrd(bytes.Compare, bytes.Equal)
|
||||
)
|
11
bytes/monoid_test.go
Normal file
11
bytes/monoid_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package bytes
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
M "github.com/ibm/fp-go/monoid/testing"
|
||||
)
|
||||
|
||||
func TestMonoid(t *testing.T) {
|
||||
M.AssertLaws(t, Monoid)([][]byte{[]byte(""), []byte("a"), []byte("some value")})
|
||||
}
|
127
cli/monad.go
Normal file
127
cli/monad.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func tupleType(i int) string {
|
||||
var buf strings.Builder
|
||||
buf.WriteString(fmt.Sprintf("T.Tuple%d[", i))
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("T%d", j+1))
|
||||
}
|
||||
buf.WriteString("]")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func monadGenerateSequenceTNonGeneric(
|
||||
hkt func(string) string,
|
||||
fmap func(string, string) string,
|
||||
fap func(string, string) string,
|
||||
) func(f *os.File, i int) {
|
||||
return func(f *os.File, i int) {
|
||||
|
||||
tuple := tupleType(i)
|
||||
|
||||
fmt.Fprintf(f, "SequenceT%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "](")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "t%d %s", j+1, hkt(fmt.Sprintf("T%d", j+1)))
|
||||
}
|
||||
fmt.Fprintf(f, ") %s {", hkt(tuple))
|
||||
// the actual apply callback
|
||||
fmt.Fprintf(f, " return Apply.SequenceT%d(\n", i)
|
||||
// map callback
|
||||
|
||||
curried := func(count int) string {
|
||||
var buf strings.Builder
|
||||
for j := count; j < i; j++ {
|
||||
buf.WriteString(fmt.Sprintf("func(T%d)", j+1))
|
||||
}
|
||||
buf.WriteString(tuple)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, " %s,\n", fmap("T1", curried(1)))
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " %s,\n", fap(curried(j+1), fmt.Sprintf("T%d", j)))
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " T%d,\n", j+1)
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, " )\n")
|
||||
|
||||
fmt.Fprintf(f, "}\n")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func monadGenerateSequenceTGeneric(
|
||||
hkt func(string) string,
|
||||
fmap func(string, string) string,
|
||||
fap func(string, string) string,
|
||||
) func(f *os.File, i int) {
|
||||
return func(f *os.File, i int) {
|
||||
|
||||
tuple := tupleType(i)
|
||||
|
||||
fmt.Fprintf(f, "SequenceT%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "](")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "t%d %s", j+1, hkt(fmt.Sprintf("T%d", j+1)))
|
||||
}
|
||||
fmt.Fprintf(f, ") %s {", hkt(tuple))
|
||||
// the actual apply callback
|
||||
fmt.Fprintf(f, " return Apply.SequenceT%d(\n", i)
|
||||
// map callback
|
||||
|
||||
curried := func(count int) string {
|
||||
var buf strings.Builder
|
||||
for j := count; j < i; j++ {
|
||||
buf.WriteString(fmt.Sprintf("func(T%d)", j+1))
|
||||
}
|
||||
buf.WriteString(tuple)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, " %s,\n", fmap("T1", curried(1)))
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " %s,\n", fap(curried(j+1), fmt.Sprintf("T%d", j)))
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " T%d,\n", j+1)
|
||||
}
|
||||
|
||||
fmt.Fprintf(f, " )\n")
|
||||
|
||||
fmt.Fprintf(f, "}\n")
|
||||
|
||||
}
|
||||
}
|
@@ -3,201 +3,200 @@
|
||||
// 2023-07-14 13:19:40.5850892 +0200 CEST m=+0.008180901
|
||||
package either
|
||||
|
||||
|
||||
// Eitherize0 converts a function with 0 parameters returning a tuple into a function with 0 parameters returning an Either
|
||||
// The inverse function is [Uneitherize0]
|
||||
func Eitherize0[F ~func() (R, error), R any](f F) func() Either[error, R] {
|
||||
return func() Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f()
|
||||
})
|
||||
}
|
||||
return func() Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize0 converts a function with 0 parameters returning an Either into a function with 0 parameters returning a tuple
|
||||
// The inverse function is [Eitherize0]
|
||||
func Uneitherize0[F ~func() Either[error, R], R any](f F) func() (R, error) {
|
||||
return func() (R, error) {
|
||||
return UnwrapError(f())
|
||||
}
|
||||
return func() (R, error) {
|
||||
return UnwrapError(f())
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize1 converts a function with 1 parameters returning a tuple into a function with 1 parameters returning an Either
|
||||
// The inverse function is [Uneitherize1]
|
||||
func Eitherize1[F ~func(T0) (R, error), T0, R any](f F) func(T0) Either[error, R] {
|
||||
return func(t0 T0) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0)
|
||||
})
|
||||
}
|
||||
return func(t0 T0) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize1 converts a function with 1 parameters returning an Either into a function with 1 parameters returning a tuple
|
||||
// The inverse function is [Eitherize1]
|
||||
func Uneitherize1[F ~func(T0) Either[error, R], T0, R any](f F) func(T0) (R, error) {
|
||||
return func(t0 T0) (R, error) {
|
||||
return UnwrapError(f(t0))
|
||||
}
|
||||
return func(t0 T0) (R, error) {
|
||||
return UnwrapError(f(t0))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize2 converts a function with 2 parameters returning a tuple into a function with 2 parameters returning an Either
|
||||
// The inverse function is [Uneitherize2]
|
||||
func Eitherize2[F ~func(T0, T1) (R, error), T0, T1, R any](f F) func(T0, T1) Either[error, R] {
|
||||
return func(t0 T0, t1 T1) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize2 converts a function with 2 parameters returning an Either into a function with 2 parameters returning a tuple
|
||||
// The inverse function is [Eitherize2]
|
||||
func Uneitherize2[F ~func(T0, T1) Either[error, R], T0, T1, R any](f F) func(T0, T1) (R, error) {
|
||||
return func(t0 T0, t1 T1) (R, error) {
|
||||
return UnwrapError(f(t0, t1))
|
||||
}
|
||||
return func(t0 T0, t1 T1) (R, error) {
|
||||
return UnwrapError(f(t0, t1))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize3 converts a function with 3 parameters returning a tuple into a function with 3 parameters returning an Either
|
||||
// The inverse function is [Uneitherize3]
|
||||
func Eitherize3[F ~func(T0, T1, T2) (R, error), T0, T1, T2, R any](f F) func(T0, T1, T2) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize3 converts a function with 3 parameters returning an Either into a function with 3 parameters returning a tuple
|
||||
// The inverse function is [Eitherize3]
|
||||
func Uneitherize3[F ~func(T0, T1, T2) Either[error, R], T0, T1, T2, R any](f F) func(T0, T1, T2) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize4 converts a function with 4 parameters returning a tuple into a function with 4 parameters returning an Either
|
||||
// The inverse function is [Uneitherize4]
|
||||
func Eitherize4[F ~func(T0, T1, T2, T3) (R, error), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize4 converts a function with 4 parameters returning an Either into a function with 4 parameters returning a tuple
|
||||
// The inverse function is [Eitherize4]
|
||||
func Uneitherize4[F ~func(T0, T1, T2, T3) Either[error, R], T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize5 converts a function with 5 parameters returning a tuple into a function with 5 parameters returning an Either
|
||||
// The inverse function is [Uneitherize5]
|
||||
func Eitherize5[F ~func(T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize5 converts a function with 5 parameters returning an Either into a function with 5 parameters returning a tuple
|
||||
// The inverse function is [Eitherize5]
|
||||
func Uneitherize5[F ~func(T0, T1, T2, T3, T4) Either[error, R], T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize6 converts a function with 6 parameters returning a tuple into a function with 6 parameters returning an Either
|
||||
// The inverse function is [Uneitherize6]
|
||||
func Eitherize6[F ~func(T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize6 converts a function with 6 parameters returning an Either into a function with 6 parameters returning a tuple
|
||||
// The inverse function is [Eitherize6]
|
||||
func Uneitherize6[F ~func(T0, T1, T2, T3, T4, T5) Either[error, R], T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize7 converts a function with 7 parameters returning a tuple into a function with 7 parameters returning an Either
|
||||
// The inverse function is [Uneitherize7]
|
||||
func Eitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, error), T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize7 converts a function with 7 parameters returning an Either into a function with 7 parameters returning a tuple
|
||||
// The inverse function is [Eitherize7]
|
||||
func Uneitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) Either[error, R], T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize8 converts a function with 8 parameters returning a tuple into a function with 8 parameters returning an Either
|
||||
// The inverse function is [Uneitherize8]
|
||||
func Eitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize8 converts a function with 8 parameters returning an Either into a function with 8 parameters returning a tuple
|
||||
// The inverse function is [Eitherize8]
|
||||
func Uneitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize9 converts a function with 9 parameters returning a tuple into a function with 9 parameters returning an Either
|
||||
// The inverse function is [Uneitherize9]
|
||||
func Eitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize9 converts a function with 9 parameters returning an Either into a function with 9 parameters returning a tuple
|
||||
// The inverse function is [Eitherize9]
|
||||
func Uneitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
}
|
||||
|
||||
// Eitherize10 converts a function with 10 parameters returning a tuple into a function with 10 parameters returning an Either
|
||||
// The inverse function is [Uneitherize10]
|
||||
func Eitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Either[error, R] {
|
||||
return TryCatchError(func() (R, error) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Uneitherize10 converts a function with 10 parameters returning an Either into a function with 10 parameters returning a tuple
|
||||
// The inverse function is [Eitherize10]
|
||||
func Uneitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, error) {
|
||||
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
}
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, E, A, B any](f func(A) Either[E, B]) func(GA) Either[E, GB] {
|
||||
return RR.Traverse[GA](
|
||||
Of[E, GB],
|
||||
MonadMap[E, GB, func(B) GB],
|
||||
MonadAp[GB, E, B],
|
||||
Map[E, GB, func(B) GB],
|
||||
Ap[GB, E, B],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
@@ -2,449 +2,453 @@
|
||||
// This file was generated by robots at
|
||||
// 2023-07-14 13:19:42.9896471 +0200 CEST m=+0.009694501
|
||||
package function
|
||||
|
||||
// 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.
|
||||
// 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 {
|
||||
return func(t1 T1) func() R {
|
||||
return func() R {
|
||||
return f(t1)
|
||||
}
|
||||
}
|
||||
return func(t1 T1) func() R {
|
||||
return func() R {
|
||||
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
|
||||
func Ignore1of1[T1 any, F ~func() R, R any](f F) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
return f()
|
||||
}
|
||||
return func(t1 T1) R {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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 {
|
||||
return func(t1 T1) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
return f(t1, t2)
|
||||
}
|
||||
}
|
||||
return func(t1 T1) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
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
|
||||
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 f(t2)
|
||||
}
|
||||
return func(t1 T1, t2 T2) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
return f(t1, t2)
|
||||
}
|
||||
}
|
||||
return func(t2 T2) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
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
|
||||
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 f(t1)
|
||||
}
|
||||
return func(t1 T1, t2 T2) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2) func() R {
|
||||
return func() R {
|
||||
return f(t1, t2)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2) func() R {
|
||||
return func() R {
|
||||
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
|
||||
func Ignore12of2[T1, T2 any, F ~func() R, R any](f F) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f()
|
||||
}
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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 {
|
||||
return func(t1 T1) func(T2, T3) R {
|
||||
return func(t2 T2, t3 T3) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t1 T1) func(T2, T3) R {
|
||||
return func(t2 T2, t3 T3) R {
|
||||
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
|
||||
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 f(t2, t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2) func(T1, T3) R {
|
||||
return func(t1 T1, t3 T3) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t2 T2) func(T1, T3) R {
|
||||
return func(t1 T1, t3 T3) R {
|
||||
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
|
||||
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 f(t1, t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t3 T3) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t3 T3) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
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
|
||||
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 f(t1, t2)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2) func(T3) R {
|
||||
return func(t3 T3) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2) func(T3) R {
|
||||
return func(t3 T3) R {
|
||||
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
|
||||
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 f(t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t3 T3) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t3 T3) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
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
|
||||
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 f(t2)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2, t3 T3) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t2 T2, t3 T3) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
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
|
||||
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 f(t1)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2, t3 T3) func() R {
|
||||
return func() R {
|
||||
return f(t1, t2, t3)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) func() R {
|
||||
return func() R {
|
||||
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
|
||||
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 f()
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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 {
|
||||
return func(t1 T1) func(T2, T3, T4) R {
|
||||
return func(t2 T2, t3 T3, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1) func(T2, T3, T4) R {
|
||||
return func(t2 T2, t3 T3, t4 T4) R {
|
||||
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
|
||||
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 f(t2, t3, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2) func(T1, T3, T4) R {
|
||||
return func(t1 T1, t3 T3, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t2 T2) func(T1, T3, T4) R {
|
||||
return func(t1 T1, t3 T3, t4 T4) R {
|
||||
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
|
||||
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 f(t1, t3, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t3 T3) func(T1, T2, T4) R {
|
||||
return func(t1 T1, t2 T2, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t3 T3) func(T1, T2, T4) R {
|
||||
return func(t1 T1, t2 T2, t4 T4) R {
|
||||
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
|
||||
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 f(t1, t2, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t4 T4) func(T1, T2, T3) R {
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t4 T4) func(T1, T2, T3) R {
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
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
|
||||
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 f(t1, t2, t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2) func(T3, T4) R {
|
||||
return func(t3 T3, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2) func(T3, T4) R {
|
||||
return func(t3 T3, t4 T4) R {
|
||||
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
|
||||
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 f(t3, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t3 T3) func(T2, T4) R {
|
||||
return func(t2 T2, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t3 T3) func(T2, T4) R {
|
||||
return func(t2 T2, t4 T4) R {
|
||||
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
|
||||
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 f(t2, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t4 T4) func(T2, T3) R {
|
||||
return func(t2 T2, t3 T3) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t4 T4) func(T2, T3) R {
|
||||
return func(t2 T2, t3 T3) R {
|
||||
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
|
||||
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 f(t2, t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2, t3 T3) func(T1, T4) R {
|
||||
return func(t1 T1, t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t2 T2, t3 T3) func(T1, T4) R {
|
||||
return func(t1 T1, t4 T4) R {
|
||||
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
|
||||
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 f(t1, t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2, t4 T4) func(T1, T3) R {
|
||||
return func(t1 T1, t3 T3) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t2 T2, t4 T4) func(T1, T3) R {
|
||||
return func(t1 T1, t3 T3) R {
|
||||
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
|
||||
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 f(t1, t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t3 T3, t4 T4) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t3 T3, t4 T4) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
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
|
||||
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 f(t1, t2)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2, t3 T3) func(T4) R {
|
||||
return func(t4 T4) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) func(T4) R {
|
||||
return func(t4 T4) R {
|
||||
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
|
||||
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 f(t4)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2, t4 T4) func(T3) R {
|
||||
return func(t3 T3) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2, t4 T4) func(T3) R {
|
||||
return func(t3 T3) R {
|
||||
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
|
||||
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 f(t3)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t3 T3, t4 T4) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t3 T3, t4 T4) func(T2) R {
|
||||
return func(t2 T2) R {
|
||||
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
|
||||
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 f(t2)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t2 T2, t3 T3, t4 T4) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t2 T2, t3 T3, t4 T4) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
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
|
||||
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 f(t1)
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
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.
|
||||
// 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 {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) func() R {
|
||||
return func() R {
|
||||
return f(t1, t2, t3, t4)
|
||||
}
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) func() R {
|
||||
return func() R {
|
||||
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
|
||||
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 f()
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
1997
function/gen.go
1997
function/gen.go
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@
|
||||
// 2023-07-14 13:19:44.2638147 +0200 CEST m=+0.009515201
|
||||
package apply
|
||||
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
@@ -11,535 +10,535 @@ import (
|
||||
|
||||
// tupleConstructor1 returns a curried version of [T.MakeTuple1]
|
||||
func tupleConstructor1[T1 any]() func(T1) T.Tuple1[T1] {
|
||||
return F.Curry1(T.MakeTuple1[T1])
|
||||
return F.Curry1(T.MakeTuple1[T1])
|
||||
}
|
||||
|
||||
// SequenceT1 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 1 higher higher kinded types and returns a higher kinded type of a [Tuple1] with the resolved values.
|
||||
func SequenceT1[
|
||||
MAP ~func(func(T1) T.Tuple1[T1]) func(HKT_T1) HKT_TUPLE1,
|
||||
T1,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_TUPLE1 any, // HKT[Tuple1[T1]]
|
||||
MAP ~func(func(T1) T.Tuple1[T1]) func(HKT_T1) HKT_TUPLE1,
|
||||
T1,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_TUPLE1 any, // HKT[Tuple1[T1]]
|
||||
](
|
||||
fmap MAP,
|
||||
t1 HKT_T1,
|
||||
fmap MAP,
|
||||
t1 HKT_T1,
|
||||
) HKT_TUPLE1 {
|
||||
return F.Pipe1(
|
||||
t1,
|
||||
fmap(tupleConstructor1[T1]()),
|
||||
)
|
||||
return F.Pipe1(
|
||||
t1,
|
||||
fmap(tupleConstructor1[T1]()),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor2 returns a curried version of [T.MakeTuple2]
|
||||
func tupleConstructor2[T1, T2 any]() func(T1) func(T2) T.Tuple2[T1, T2] {
|
||||
return F.Curry2(T.MakeTuple2[T1, T2])
|
||||
return F.Curry2(T.MakeTuple2[T1, T2])
|
||||
}
|
||||
|
||||
// SequenceT2 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 2 higher higher kinded types and returns a higher kinded type of a [Tuple2] with the resolved values.
|
||||
func SequenceT2[
|
||||
MAP ~func(func(T1) func(T2) T.Tuple2[T1, T2]) func(HKT_T1) HKT_F_T2,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2) HKT_TUPLE2,
|
||||
T1,
|
||||
T2,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_F_T2, // HKT[func(T2) T.Tuple2[T1, T2]]
|
||||
HKT_TUPLE2 any, // HKT[Tuple2[T1, T2]]
|
||||
MAP ~func(func(T1) func(T2) T.Tuple2[T1, T2]) func(HKT_T1) HKT_F_T2,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2) HKT_TUPLE2,
|
||||
T1,
|
||||
T2,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_F_T2, // HKT[func(T2) T.Tuple2[T1, T2]]
|
||||
HKT_TUPLE2 any, // HKT[Tuple2[T1, T2]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
) HKT_TUPLE2 {
|
||||
return F.Pipe2(
|
||||
t1,
|
||||
fmap(tupleConstructor2[T1, T2]()),
|
||||
fap1(t2),
|
||||
)
|
||||
return F.Pipe2(
|
||||
t1,
|
||||
fmap(tupleConstructor2[T1, T2]()),
|
||||
fap1(t2),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor3 returns a curried version of [T.MakeTuple3]
|
||||
func tupleConstructor3[T1, T2, T3 any]() func(T1) func(T2) func(T3) T.Tuple3[T1, T2, T3] {
|
||||
return F.Curry3(T.MakeTuple3[T1, T2, T3])
|
||||
return F.Curry3(T.MakeTuple3[T1, T2, T3])
|
||||
}
|
||||
|
||||
// SequenceT3 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 3 higher higher kinded types and returns a higher kinded type of a [Tuple3] with the resolved values.
|
||||
func SequenceT3[
|
||||
MAP ~func(func(T1) func(T2) func(T3) T.Tuple3[T1, T2, T3]) func(HKT_T1) HKT_F_T2_T3,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3) HKT_F_T3,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3) HKT_TUPLE3,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_F_T2_T3, // HKT[func(T2) func(T3) T.Tuple3[T1, T2, T3]]
|
||||
HKT_F_T3, // HKT[func(T3) T.Tuple3[T1, T2, T3]]
|
||||
HKT_TUPLE3 any, // HKT[Tuple3[T1, T2, T3]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) T.Tuple3[T1, T2, T3]) func(HKT_T1) HKT_F_T2_T3,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3) HKT_F_T3,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3) HKT_TUPLE3,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_F_T2_T3, // HKT[func(T2) func(T3) T.Tuple3[T1, T2, T3]]
|
||||
HKT_F_T3, // HKT[func(T3) T.Tuple3[T1, T2, T3]]
|
||||
HKT_TUPLE3 any, // HKT[Tuple3[T1, T2, T3]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
) HKT_TUPLE3 {
|
||||
return F.Pipe3(
|
||||
t1,
|
||||
fmap(tupleConstructor3[T1, T2, T3]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
)
|
||||
return F.Pipe3(
|
||||
t1,
|
||||
fmap(tupleConstructor3[T1, T2, T3]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor4 returns a curried version of [T.MakeTuple4]
|
||||
func tupleConstructor4[T1, T2, T3, T4 any]() func(T1) func(T2) func(T3) func(T4) T.Tuple4[T1, T2, T3, T4] {
|
||||
return F.Curry4(T.MakeTuple4[T1, T2, T3, T4])
|
||||
return F.Curry4(T.MakeTuple4[T1, T2, T3, T4])
|
||||
}
|
||||
|
||||
// SequenceT4 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 4 higher higher kinded types and returns a higher kinded type of a [Tuple4] with the resolved values.
|
||||
func SequenceT4[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]) func(HKT_T1) HKT_F_T2_T3_T4,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4) HKT_F_T3_T4,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4) HKT_F_T4,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4) HKT_TUPLE4,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_F_T2_T3_T4, // HKT[func(T2) func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_F_T3_T4, // HKT[func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_F_T4, // HKT[func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_TUPLE4 any, // HKT[Tuple4[T1, T2, T3, T4]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]) func(HKT_T1) HKT_F_T2_T3_T4,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4) HKT_F_T3_T4,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4) HKT_F_T4,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4) HKT_TUPLE4,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_F_T2_T3_T4, // HKT[func(T2) func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_F_T3_T4, // HKT[func(T3) func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_F_T4, // HKT[func(T4) T.Tuple4[T1, T2, T3, T4]]
|
||||
HKT_TUPLE4 any, // HKT[Tuple4[T1, T2, T3, T4]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
) HKT_TUPLE4 {
|
||||
return F.Pipe4(
|
||||
t1,
|
||||
fmap(tupleConstructor4[T1, T2, T3, T4]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
)
|
||||
return F.Pipe4(
|
||||
t1,
|
||||
fmap(tupleConstructor4[T1, T2, T3, T4]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor5 returns a curried version of [T.MakeTuple5]
|
||||
func tupleConstructor5[T1, T2, T3, T4, T5 any]() func(T1) func(T2) func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5] {
|
||||
return F.Curry5(T.MakeTuple5[T1, T2, T3, T4, T5])
|
||||
return F.Curry5(T.MakeTuple5[T1, T2, T3, T4, T5])
|
||||
}
|
||||
|
||||
// SequenceT5 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 5 higher higher kinded types and returns a higher kinded type of a [Tuple5] with the resolved values.
|
||||
func SequenceT5[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]) func(HKT_T1) HKT_F_T2_T3_T4_T5,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5) HKT_F_T3_T4_T5,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5) HKT_F_T4_T5,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5) HKT_F_T5,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5) HKT_TUPLE5,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_F_T2_T3_T4_T5, // HKT[func(T2) func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T3_T4_T5, // HKT[func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T4_T5, // HKT[func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T5, // HKT[func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_TUPLE5 any, // HKT[Tuple5[T1, T2, T3, T4, T5]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]) func(HKT_T1) HKT_F_T2_T3_T4_T5,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5) HKT_F_T3_T4_T5,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5) HKT_F_T4_T5,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5) HKT_F_T5,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5) HKT_TUPLE5,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_F_T2_T3_T4_T5, // HKT[func(T2) func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T3_T4_T5, // HKT[func(T3) func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T4_T5, // HKT[func(T4) func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_F_T5, // HKT[func(T5) T.Tuple5[T1, T2, T3, T4, T5]]
|
||||
HKT_TUPLE5 any, // HKT[Tuple5[T1, T2, T3, T4, T5]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
) HKT_TUPLE5 {
|
||||
return F.Pipe5(
|
||||
t1,
|
||||
fmap(tupleConstructor5[T1, T2, T3, T4, T5]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
)
|
||||
return F.Pipe5(
|
||||
t1,
|
||||
fmap(tupleConstructor5[T1, T2, T3, T4, T5]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor6 returns a curried version of [T.MakeTuple6]
|
||||
func tupleConstructor6[T1, T2, T3, T4, T5, T6 any]() func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6] {
|
||||
return F.Curry6(T.MakeTuple6[T1, T2, T3, T4, T5, T6])
|
||||
return F.Curry6(T.MakeTuple6[T1, T2, T3, T4, T5, T6])
|
||||
}
|
||||
|
||||
// SequenceT6 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 6 higher higher kinded types and returns a higher kinded type of a [Tuple6] with the resolved values.
|
||||
func SequenceT6[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6) HKT_F_T3_T4_T5_T6,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6) HKT_F_T4_T5_T6,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6) HKT_F_T5_T6,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6) HKT_F_T6,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6) HKT_TUPLE6,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_F_T2_T3_T4_T5_T6, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T3_T4_T5_T6, // HKT[func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T4_T5_T6, // HKT[func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T5_T6, // HKT[func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T6, // HKT[func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_TUPLE6 any, // HKT[Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6) HKT_F_T3_T4_T5_T6,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6) HKT_F_T4_T5_T6,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6) HKT_F_T5_T6,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6) HKT_F_T6,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6) HKT_TUPLE6,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_F_T2_T3_T4_T5_T6, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T3_T4_T5_T6, // HKT[func(T3) func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T4_T5_T6, // HKT[func(T4) func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T5_T6, // HKT[func(T5) func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_F_T6, // HKT[func(T6) T.Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
HKT_TUPLE6 any, // HKT[Tuple6[T1, T2, T3, T4, T5, T6]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
) HKT_TUPLE6 {
|
||||
return F.Pipe6(
|
||||
t1,
|
||||
fmap(tupleConstructor6[T1, T2, T3, T4, T5, T6]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
)
|
||||
return F.Pipe6(
|
||||
t1,
|
||||
fmap(tupleConstructor6[T1, T2, T3, T4, T5, T6]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor7 returns a curried version of [T.MakeTuple7]
|
||||
func tupleConstructor7[T1, T2, T3, T4, T5, T6, T7 any]() func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7] {
|
||||
return F.Curry7(T.MakeTuple7[T1, T2, T3, T4, T5, T6, T7])
|
||||
return F.Curry7(T.MakeTuple7[T1, T2, T3, T4, T5, T6, T7])
|
||||
}
|
||||
|
||||
// SequenceT7 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 7 higher higher kinded types and returns a higher kinded type of a [Tuple7] with the resolved values.
|
||||
func SequenceT7[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7) HKT_F_T3_T4_T5_T6_T7,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7) HKT_F_T4_T5_T6_T7,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7) HKT_F_T5_T6_T7,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7) HKT_F_T6_T7,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7) HKT_F_T7,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7) HKT_TUPLE7,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T3_T4_T5_T6_T7, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T4_T5_T6_T7, // HKT[func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T5_T6_T7, // HKT[func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T6_T7, // HKT[func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T7, // HKT[func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_TUPLE7 any, // HKT[Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7) HKT_F_T3_T4_T5_T6_T7,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7) HKT_F_T4_T5_T6_T7,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7) HKT_F_T5_T6_T7,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7) HKT_F_T6_T7,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7) HKT_F_T7,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7) HKT_TUPLE7,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T3_T4_T5_T6_T7, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T4_T5_T6_T7, // HKT[func(T4) func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T5_T6_T7, // HKT[func(T5) func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T6_T7, // HKT[func(T6) func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_F_T7, // HKT[func(T7) T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
HKT_TUPLE7 any, // HKT[Tuple7[T1, T2, T3, T4, T5, T6, T7]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
) HKT_TUPLE7 {
|
||||
return F.Pipe7(
|
||||
t1,
|
||||
fmap(tupleConstructor7[T1, T2, T3, T4, T5, T6, T7]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
)
|
||||
return F.Pipe7(
|
||||
t1,
|
||||
fmap(tupleConstructor7[T1, T2, T3, T4, T5, T6, T7]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor8 returns a curried version of [T.MakeTuple8]
|
||||
func tupleConstructor8[T1, T2, T3, T4, T5, T6, T7, T8 any]() func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] {
|
||||
return F.Curry8(T.MakeTuple8[T1, T2, T3, T4, T5, T6, T7, T8])
|
||||
return F.Curry8(T.MakeTuple8[T1, T2, T3, T4, T5, T6, T7, T8])
|
||||
}
|
||||
|
||||
// SequenceT8 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 8 higher higher kinded types and returns a higher kinded type of a [Tuple8] with the resolved values.
|
||||
func SequenceT8[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8) HKT_F_T3_T4_T5_T6_T7_T8,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8) HKT_F_T4_T5_T6_T7_T8,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8) HKT_F_T5_T6_T7_T8,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8) HKT_F_T6_T7_T8,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8) HKT_F_T7_T8,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8) HKT_F_T8,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8) HKT_TUPLE8,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T4_T5_T6_T7_T8, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T5_T6_T7_T8, // HKT[func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T6_T7_T8, // HKT[func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T7_T8, // HKT[func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T8, // HKT[func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_TUPLE8 any, // HKT[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8) HKT_F_T3_T4_T5_T6_T7_T8,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8) HKT_F_T4_T5_T6_T7_T8,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8) HKT_F_T5_T6_T7_T8,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8) HKT_F_T6_T7_T8,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8) HKT_F_T7_T8,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8) HKT_F_T8,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8) HKT_TUPLE8,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T4_T5_T6_T7_T8, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T5_T6_T7_T8, // HKT[func(T5) func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T6_T7_T8, // HKT[func(T6) func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T7_T8, // HKT[func(T7) func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_F_T8, // HKT[func(T8) T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
HKT_TUPLE8 any, // HKT[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
) HKT_TUPLE8 {
|
||||
return F.Pipe8(
|
||||
t1,
|
||||
fmap(tupleConstructor8[T1, T2, T3, T4, T5, T6, T7, T8]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
)
|
||||
return F.Pipe8(
|
||||
t1,
|
||||
fmap(tupleConstructor8[T1, T2, T3, T4, T5, T6, T7, T8]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor9 returns a curried version of [T.MakeTuple9]
|
||||
func tupleConstructor9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any]() func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] {
|
||||
return F.Curry9(T.MakeTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9])
|
||||
return F.Curry9(T.MakeTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9])
|
||||
}
|
||||
|
||||
// SequenceT9 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 9 higher higher kinded types and returns a higher kinded type of a [Tuple9] with the resolved values.
|
||||
func SequenceT9[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8_T9,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8_T9) HKT_F_T3_T4_T5_T6_T7_T8_T9,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8_T9) HKT_F_T4_T5_T6_T7_T8_T9,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8_T9) HKT_F_T5_T6_T7_T8_T9,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8_T9) HKT_F_T6_T7_T8_T9,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8_T9) HKT_F_T7_T8_T9,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8_T9) HKT_F_T8_T9,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8_T9) HKT_F_T9,
|
||||
AP8 ~func(HKT_T9) func(HKT_F_T9) HKT_TUPLE9,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
T9,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_T9, // HKT[T9]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8_T9, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8_T9, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T4_T5_T6_T7_T8_T9, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T5_T6_T7_T8_T9, // HKT[func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T6_T7_T8_T9, // HKT[func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T7_T8_T9, // HKT[func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T8_T9, // HKT[func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T9, // HKT[func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_TUPLE9 any, // HKT[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8_T9,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8_T9) HKT_F_T3_T4_T5_T6_T7_T8_T9,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8_T9) HKT_F_T4_T5_T6_T7_T8_T9,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8_T9) HKT_F_T5_T6_T7_T8_T9,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8_T9) HKT_F_T6_T7_T8_T9,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8_T9) HKT_F_T7_T8_T9,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8_T9) HKT_F_T8_T9,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8_T9) HKT_F_T9,
|
||||
AP8 ~func(HKT_T9) func(HKT_F_T9) HKT_TUPLE9,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
T9,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_T9, // HKT[T9]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8_T9, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8_T9, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T4_T5_T6_T7_T8_T9, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T5_T6_T7_T8_T9, // HKT[func(T5) func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T6_T7_T8_T9, // HKT[func(T6) func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T7_T8_T9, // HKT[func(T7) func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T8_T9, // HKT[func(T8) func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_F_T9, // HKT[func(T9) T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
HKT_TUPLE9 any, // HKT[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
fap8 AP8,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
t9 HKT_T9,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
fap8 AP8,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
t9 HKT_T9,
|
||||
) HKT_TUPLE9 {
|
||||
return F.Pipe9(
|
||||
t1,
|
||||
fmap(tupleConstructor9[T1, T2, T3, T4, T5, T6, T7, T8, T9]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
fap8(t9),
|
||||
)
|
||||
return F.Pipe9(
|
||||
t1,
|
||||
fmap(tupleConstructor9[T1, T2, T3, T4, T5, T6, T7, T8, T9]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
fap8(t9),
|
||||
)
|
||||
}
|
||||
|
||||
// tupleConstructor10 returns a curried version of [T.MakeTuple10]
|
||||
func tupleConstructor10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any]() func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {
|
||||
return F.Curry10(T.MakeTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10])
|
||||
return F.Curry10(T.MakeTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10])
|
||||
}
|
||||
|
||||
// SequenceT10 is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||
// The function takes 10 higher higher kinded types and returns a higher kinded type of a [Tuple10] with the resolved values.
|
||||
func SequenceT10[
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10) HKT_F_T3_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8_T9_T10) HKT_F_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8_T9_T10) HKT_F_T5_T6_T7_T8_T9_T10,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8_T9_T10) HKT_F_T6_T7_T8_T9_T10,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8_T9_T10) HKT_F_T7_T8_T9_T10,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8_T9_T10) HKT_F_T8_T9_T10,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8_T9_T10) HKT_F_T9_T10,
|
||||
AP8 ~func(HKT_T9) func(HKT_F_T9_T10) HKT_F_T10,
|
||||
AP9 ~func(HKT_T10) func(HKT_F_T10) HKT_TUPLE10,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
T9,
|
||||
T10,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_T9, // HKT[T9]
|
||||
HKT_T10, // HKT[T10]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T5_T6_T7_T8_T9_T10, // HKT[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T6_T7_T8_T9_T10, // HKT[func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T7_T8_T9_T10, // HKT[func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T8_T9_T10, // HKT[func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T9_T10, // HKT[func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T10, // HKT[func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_TUPLE10 any, // HKT[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
MAP ~func(func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) func(HKT_T1) HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP1 ~func(HKT_T2) func(HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10) HKT_F_T3_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP2 ~func(HKT_T3) func(HKT_F_T3_T4_T5_T6_T7_T8_T9_T10) HKT_F_T4_T5_T6_T7_T8_T9_T10,
|
||||
AP3 ~func(HKT_T4) func(HKT_F_T4_T5_T6_T7_T8_T9_T10) HKT_F_T5_T6_T7_T8_T9_T10,
|
||||
AP4 ~func(HKT_T5) func(HKT_F_T5_T6_T7_T8_T9_T10) HKT_F_T6_T7_T8_T9_T10,
|
||||
AP5 ~func(HKT_T6) func(HKT_F_T6_T7_T8_T9_T10) HKT_F_T7_T8_T9_T10,
|
||||
AP6 ~func(HKT_T7) func(HKT_F_T7_T8_T9_T10) HKT_F_T8_T9_T10,
|
||||
AP7 ~func(HKT_T8) func(HKT_F_T8_T9_T10) HKT_F_T9_T10,
|
||||
AP8 ~func(HKT_T9) func(HKT_F_T9_T10) HKT_F_T10,
|
||||
AP9 ~func(HKT_T10) func(HKT_F_T10) HKT_TUPLE10,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
T5,
|
||||
T6,
|
||||
T7,
|
||||
T8,
|
||||
T9,
|
||||
T10,
|
||||
HKT_T1, // HKT[T1]
|
||||
HKT_T2, // HKT[T2]
|
||||
HKT_T3, // HKT[T3]
|
||||
HKT_T4, // HKT[T4]
|
||||
HKT_T5, // HKT[T5]
|
||||
HKT_T6, // HKT[T6]
|
||||
HKT_T7, // HKT[T7]
|
||||
HKT_T8, // HKT[T8]
|
||||
HKT_T9, // HKT[T9]
|
||||
HKT_T10, // HKT[T10]
|
||||
HKT_F_T2_T3_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T3_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T4_T5_T6_T7_T8_T9_T10, // HKT[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T5_T6_T7_T8_T9_T10, // HKT[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T6_T7_T8_T9_T10, // HKT[func(T6) func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T7_T8_T9_T10, // HKT[func(T7) func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T8_T9_T10, // HKT[func(T8) func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T9_T10, // HKT[func(T9) func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_F_T10, // HKT[func(T10) T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
HKT_TUPLE10 any, // HKT[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]
|
||||
](
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
fap8 AP8,
|
||||
fap9 AP9,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
t9 HKT_T9,
|
||||
t10 HKT_T10,
|
||||
fmap MAP,
|
||||
fap1 AP1,
|
||||
fap2 AP2,
|
||||
fap3 AP3,
|
||||
fap4 AP4,
|
||||
fap5 AP5,
|
||||
fap6 AP6,
|
||||
fap7 AP7,
|
||||
fap8 AP8,
|
||||
fap9 AP9,
|
||||
t1 HKT_T1,
|
||||
t2 HKT_T2,
|
||||
t3 HKT_T3,
|
||||
t4 HKT_T4,
|
||||
t5 HKT_T5,
|
||||
t6 HKT_T6,
|
||||
t7 HKT_T7,
|
||||
t8 HKT_T8,
|
||||
t9 HKT_T9,
|
||||
t10 HKT_T10,
|
||||
) HKT_TUPLE10 {
|
||||
return F.Pipe10(
|
||||
t1,
|
||||
fmap(tupleConstructor10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
fap8(t9),
|
||||
fap9(t10),
|
||||
)
|
||||
return F.Pipe10(
|
||||
t1,
|
||||
fmap(tupleConstructor10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]()),
|
||||
fap1(t2),
|
||||
fap2(t3),
|
||||
fap3(t4),
|
||||
fap4(t5),
|
||||
fap5(t6),
|
||||
fap6(t7),
|
||||
fap7(t8),
|
||||
fap8(t9),
|
||||
fap9(t10),
|
||||
)
|
||||
}
|
||||
|
@@ -13,31 +13,31 @@ HKTB = HKT<B>
|
||||
HKTAB = HKT<func(A)B>
|
||||
*/
|
||||
func MonadTraverse[GA ~[]A, GB ~[]B, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(GB) HKTRB,
|
||||
_map func(HKTRB, func(GB) func(B) GB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(GB) HKTRB,
|
||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
ta GA,
|
||||
f func(A) HKTB) HKTRB {
|
||||
return MonadTraverseReduce(_of, _map, _ap, ta, f, Append[GB, B], Empty[GB]())
|
||||
return MonadTraverseReduce(fof, fmap, fap, ta, f, Append[GB, B], Empty[GB]())
|
||||
}
|
||||
|
||||
func Traverse[GA ~[]A, GB ~[]B, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(GB) HKTRB,
|
||||
_map func(HKTRB, func(GB) func(B) GB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(GB) HKTRB,
|
||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
f func(A) HKTB) func(GA) HKTRB {
|
||||
|
||||
return func(ma GA) HKTRB {
|
||||
return MonadTraverse(_of, _map, _ap, ma, f)
|
||||
return MonadTraverse(fof, fmap, fap, ma, f)
|
||||
}
|
||||
}
|
||||
|
||||
func MonadTraverseReduce[GA ~[]A, GB, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(GB) HKTRB,
|
||||
_map func(HKTRB, func(GB) func(B) GB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(GB) HKTRB,
|
||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
ta GA,
|
||||
|
||||
@@ -45,26 +45,27 @@ func MonadTraverseReduce[GA ~[]A, GB, A, B, HKTB, HKTAB, HKTRB any](
|
||||
reduce func(GB, B) GB,
|
||||
initial GB,
|
||||
) HKTRB {
|
||||
mmap := F.Bind2nd(_map, F.Curry2(reduce))
|
||||
mmap := fmap(F.Curry2(reduce))
|
||||
|
||||
return Reduce(ta, func(r HKTRB, a A) HKTRB {
|
||||
return _ap(
|
||||
mmap(r),
|
||||
transform(a),
|
||||
return F.Pipe2(
|
||||
r,
|
||||
mmap,
|
||||
fap(transform(a)),
|
||||
)
|
||||
}, _of(initial))
|
||||
}, fof(initial))
|
||||
}
|
||||
|
||||
func TraverseReduce[GA ~[]A, GB, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(GB) HKTRB,
|
||||
_map func(HKTRB, func(GB) func(B) GB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(GB) HKTRB,
|
||||
fmap func(func(GB) func(B) GB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
transform func(A) HKTB,
|
||||
reduce func(GB, B) GB,
|
||||
initial GB,
|
||||
) func(GA) HKTRB {
|
||||
return func(ta GA) HKTRB {
|
||||
return MonadTraverseReduce(_of, _map, _ap, ta, transform, reduce, initial)
|
||||
return MonadTraverseReduce(fof, fmap, fap, ta, transform, reduce, initial)
|
||||
}
|
||||
}
|
||||
|
108
internal/eithert/either.go
Normal file
108
internal/eithert/either.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package eithert
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/ibm/fp-go/internal/apply"
|
||||
FC "github.com/ibm/fp-go/internal/functor"
|
||||
)
|
||||
|
||||
// HKTFA = HKT<F, Either<E, A>>
|
||||
// HKTFB = HKT<F, Either<E, B>>
|
||||
func MonadMap[E, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E, A]) ET.Either[E, B]) HKTFB, fa HKTFA, f func(A) B) HKTFB {
|
||||
// HKTGA = Either[E, A]
|
||||
// HKTGB = Either[E, B]
|
||||
return FC.MonadMap(fmap, ET.MonadMap[E, A, B], fa, f)
|
||||
}
|
||||
|
||||
// HKTFA = HKT<F, Either<E, A>>
|
||||
// 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 {
|
||||
// HKTGA = Either[E, A]
|
||||
// HKTGB = Either[E, B]
|
||||
return fmap(fa, ET.BiMap(f, g))
|
||||
}
|
||||
|
||||
// HKTFA = HKT<F, Either<E, A>>
|
||||
// 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 {
|
||||
// HKTGA = Either[E, A]
|
||||
// HKTGB = Either[E, B]
|
||||
return F.Bind2nd(fmap, ET.BiMap(f, g))
|
||||
}
|
||||
|
||||
// HKTFA = HKT<F, Either<E, A>>
|
||||
// HKTFB = HKT<F, Either<E, B>>
|
||||
func MonadChain[E, A, B, HKTFA, HKTFB any](
|
||||
fchain func(HKTFA, func(ET.Either[E, A]) HKTFB) HKTFB,
|
||||
fof func(ET.Either[E, B]) HKTFB,
|
||||
ma HKTFA,
|
||||
f func(A) HKTFB) HKTFB {
|
||||
// dispatch to the even more generic implementation
|
||||
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
|
||||
|
||||
// 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](
|
||||
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,
|
||||
fab HKTFAB,
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func Left[E, A, HKTA any](fof func(ET.Either[E, A]) HKTA, e E) HKTA {
|
||||
return F.Pipe2(e, ET.Left[A, E], fof)
|
||||
}
|
||||
|
||||
// HKTA = HKT[A]
|
||||
// HKTEA = HKT[Either[E, A]]
|
||||
func RightF[E, A, HKTA, HKTEA any](fmap func(HKTA, func(A) ET.Either[E, A]) HKTEA, fa HKTA) HKTEA {
|
||||
return fmap(fa, ET.Right[E, A])
|
||||
}
|
||||
|
||||
// HKTE = HKT[E]
|
||||
// HKTEA = HKT[Either[E, A]]
|
||||
func LeftF[E, A, HKTE, HKTEA any](fmap func(HKTE, func(E) ET.Either[E, A]) HKTEA, fe HKTE) HKTEA {
|
||||
return fmap(fe, ET.Left[A, E])
|
||||
}
|
||||
|
||||
func FoldE[E, A, HKTEA, HKTB any](mchain func(HKTEA, func(ET.Either[E, A]) HKTB) HKTB, ma HKTEA, onLeft func(E) HKTB, onRight func(A) HKTB) HKTB {
|
||||
return mchain(ma, ET.Fold(onLeft, onRight))
|
||||
}
|
||||
|
||||
func MatchE[E, A, HKTEA, HKTB any](mchain func(HKTEA, func(ET.Either[E, A]) HKTB) HKTB, onLeft func(E) HKTB, onRight func(A) HKTB) func(HKTEA) HKTB {
|
||||
return F.Bind2nd(mchain, ET.Fold(onLeft, onRight))
|
||||
}
|
||||
|
||||
func GetOrElse[E, A, HKTEA, HKTA any](mchain func(HKTEA, func(ET.Either[E, A]) HKTA) HKTA, mof func(A) HKTA, onLeft func(E) HKTA) func(HKTEA) HKTA {
|
||||
return MatchE(mchain, onLeft, mof)
|
||||
}
|
||||
|
||||
func OrElse[E1, E2, A, HKTE1A, HKTE2A any](mchain func(HKTE1A, func(ET.Either[E1, A]) HKTE2A) HKTE2A, mof func(ET.Either[E2, A]) HKTE2A, onLeft func(E1) HKTE2A) func(HKTE1A) HKTE2A {
|
||||
return MatchE(mchain, onLeft, F.Flow2(ET.Right[E2, A], mof))
|
||||
}
|
||||
|
||||
func OrLeft[E1, E2, A, HKTE1A, HKTE2, HKTE2A any](
|
||||
mchain func(HKTE1A, func(ET.Either[E1, A]) HKTE2A) HKTE2A,
|
||||
mmap func(HKTE2, func(E2) ET.Either[E2, A]) HKTE2A,
|
||||
mof func(ET.Either[E2, A]) HKTE2A,
|
||||
onLeft func(E1) HKTE2) func(HKTE1A) HKTE2A {
|
||||
|
||||
return F.Bind2nd(mchain, ET.Fold(F.Flow2(onLeft, F.Bind2nd(mmap, ET.Left[A, E2])), F.Flow2(ET.Right[E2, A], mof)))
|
||||
}
|
||||
|
||||
func MonadMapLeft[E, A, B, HKTFA, HKTFB any](fmap func(HKTFA, func(ET.Either[E, A]) ET.Either[B, A]) HKTFB, fa HKTFA, f func(E) B) HKTFB {
|
||||
return FC.MonadMap(fmap, ET.MonadMapLeft[E, A, B], fa, f)
|
||||
}
|
19
internal/eq/eq.go
Normal file
19
internal/eq/eq.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package eq
|
||||
|
||||
import (
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
)
|
||||
|
||||
// Eq implements an equals predicate on the basis of `map` and `ap`
|
||||
func Eq[HKTA, HKTABOOL, HKTBOOL, A any](
|
||||
fmap func(HKTA, func(A) func(A) bool) HKTABOOL,
|
||||
fap func(HKTABOOL, HKTA) HKTBOOL,
|
||||
|
||||
e EQ.Eq[A],
|
||||
) func(l, r HKTA) HKTBOOL {
|
||||
c := F.Curry2(e.Equals)
|
||||
return func(fl, fr HKTA) HKTBOOL {
|
||||
return fap(fmap(fl, c), fr)
|
||||
}
|
||||
}
|
37
internal/file/bracket.go
Normal file
37
internal/file/bracket.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
)
|
||||
|
||||
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||
// whether the body action returns and error or not.
|
||||
func Bracket[
|
||||
GA, // IOEither[E, A]
|
||||
GB, // IOEither[E, A]
|
||||
GANY, // IOEither[E, ANY]
|
||||
|
||||
EB, // Either[E, B]
|
||||
|
||||
A, B, ANY any](
|
||||
|
||||
ofeb func(EB) GB,
|
||||
|
||||
chainab func(GA, func(A) GB) GB,
|
||||
chainebb func(GB, func(EB) GB) GB,
|
||||
chainany func(GANY, func(ANY) GB) GB,
|
||||
|
||||
acquire GA,
|
||||
use func(A) GB,
|
||||
release func(A, EB) GANY,
|
||||
) GB {
|
||||
return chainab(acquire,
|
||||
func(a A) GB {
|
||||
return chainebb(use(a), func(eb EB) GB {
|
||||
return chainany(
|
||||
release(a, eb),
|
||||
F.Constant1[ANY](ofeb(eb)),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
39
internal/file/file.go
Normal file
39
internal/file/file.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
)
|
||||
|
||||
type (
|
||||
readerWithContext struct {
|
||||
ctx context.Context
|
||||
delegate io.Reader
|
||||
}
|
||||
)
|
||||
|
||||
func (rdr *readerWithContext) Read(p []byte) (int, error) {
|
||||
// check for cancellarion
|
||||
if err := rdr.ctx.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// simply dispatch
|
||||
return rdr.delegate.Read(p)
|
||||
}
|
||||
|
||||
// MakeReader creates a context aware reader
|
||||
func MakeReader(ctx context.Context, rdr io.Reader) io.Reader {
|
||||
return &readerWithContext{ctx, rdr}
|
||||
}
|
||||
|
||||
// ReadAll reads the content of a reader and allows it to be canceled
|
||||
func ReadAll(ctx context.Context, rdr io.Reader) E.Either[error, []byte] {
|
||||
return E.TryCatchError(func() ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
_, err := io.Copy(&buffer, MakeReader(ctx, rdr))
|
||||
return buffer.Bytes(), err
|
||||
})
|
||||
}
|
49
internal/file/resource.go
Normal file
49
internal/file/resource.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
)
|
||||
|
||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||
func WithResource[
|
||||
GA,
|
||||
GR,
|
||||
GANY,
|
||||
E, R, A, ANY any](
|
||||
mchain func(GR, func(R) GA) GA,
|
||||
mfold1 func(GA, func(E) GA, func(A) GA) GA,
|
||||
mfold2 func(GANY, func(E) GA, func(ANY) GA) GA,
|
||||
mmap func(GANY, func(ANY) A) GA,
|
||||
left func(E) GA,
|
||||
) func(onCreate func() GR, onRelease func(R) GANY) func(func(R) GA) GA {
|
||||
|
||||
return func(onCreate func() GR, onRelease func(R) GANY) func(func(R) GA) GA {
|
||||
|
||||
return func(f func(R) GA) GA {
|
||||
return mchain(
|
||||
onCreate(), func(r R) GA {
|
||||
// handle errors
|
||||
return mfold1(
|
||||
f(r),
|
||||
func(e E) GA {
|
||||
// the original error
|
||||
err := left(e)
|
||||
// if resource processing produced and error, still release the resource but return the first error
|
||||
return mfold2(
|
||||
onRelease(r),
|
||||
F.Constant1[E](err),
|
||||
F.Constant1[ANY](err),
|
||||
)
|
||||
},
|
||||
func(a A) GA {
|
||||
// if resource processing succeeded, release the resource. If this fails return failure, else the original error
|
||||
return F.Pipe1(
|
||||
onRelease(r),
|
||||
F.Bind2nd(mmap, F.Constant1[ANY](a)),
|
||||
)
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
53
internal/fromeither/either.go
Normal file
53
internal/fromeither/either.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package fromeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
)
|
||||
|
||||
func FromOption[E, A, HKTEA any](fromEither func(ET.Either[E, A]) HKTEA, onNone func() E) func(ma O.Option[A]) HKTEA {
|
||||
return F.Flow2(ET.FromOption[E, A](onNone), fromEither)
|
||||
}
|
||||
|
||||
func FromPredicate[E, A, HKTEA any](fromEither func(ET.Either[E, A]) HKTEA, pred func(A) bool, onFalse func(A) E) func(A) HKTEA {
|
||||
return F.Flow2(ET.FromPredicate(pred, onFalse), fromEither)
|
||||
}
|
||||
|
||||
func MonadFromOption[E, A, HKTEA any](
|
||||
fromEither func(ET.Either[E, A]) HKTEA,
|
||||
onNone func() E,
|
||||
ma O.Option[A],
|
||||
) HKTEA {
|
||||
return F.Pipe1(
|
||||
O.MonadFold(
|
||||
ma,
|
||||
F.Nullary2(onNone, ET.Left[A, E]),
|
||||
ET.Right[E, A],
|
||||
),
|
||||
fromEither,
|
||||
)
|
||||
}
|
||||
|
||||
func FromOptionK[E, A, B, HKTEB any](
|
||||
fromEither func(ET.Either[E, B]) HKTEB,
|
||||
onNone func() E) func(f func(A) O.Option[B]) func(A) HKTEB {
|
||||
// helper
|
||||
return F.Bind2nd(F.Flow2[func(A) O.Option[B], func(O.Option[B]) HKTEB, A, O.Option[B], HKTEB], FromOption(fromEither, onNone))
|
||||
}
|
||||
|
||||
func MonadChainEitherK[A, E, B, HKTEA, HKTEB any](
|
||||
mchain func(HKTEA, func(A) HKTEB) HKTEB,
|
||||
fromEither func(ET.Either[E, B]) HKTEB,
|
||||
ma HKTEA,
|
||||
f func(A) ET.Either[E, B]) HKTEB {
|
||||
return mchain(ma, F.Flow2(f, fromEither))
|
||||
}
|
||||
|
||||
func ChainOptionK[A, E, B, HKTEA, HKTEB any](
|
||||
mchain func(HKTEA, func(A) HKTEB) HKTEB,
|
||||
fromEither func(ET.Either[E, B]) HKTEB,
|
||||
onNone func() E,
|
||||
) func(f func(A) O.Option[B]) func(ma HKTEA) HKTEB {
|
||||
return F.Flow2(FromOptionK[E, A](fromEither, onNone), F.Bind1st(F.Bind2nd[HKTEA, func(A) HKTEB, HKTEB], mchain))
|
||||
}
|
40
internal/fromio/io.go
Normal file
40
internal/fromio/io.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package fromio
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
C "github.com/ibm/fp-go/internal/chain"
|
||||
)
|
||||
|
||||
func MonadChainFirstIOK[A, B, HKTA, HKTB any, GIOB ~func() B](
|
||||
mchain func(HKTA, func(A) HKTA) HKTA,
|
||||
mmap func(HKTB, func(B) A) HKTA,
|
||||
fromio func(GIOB) HKTB,
|
||||
first HKTA, f func(A) GIOB) HKTA {
|
||||
// chain
|
||||
return C.MonadChainFirst(mchain, mmap, first, F.Flow2(f, fromio))
|
||||
}
|
||||
|
||||
func ChainFirstIOK[A, B, HKTA, HKTB any, GIOB ~func() B](
|
||||
mchain func(HKTA, func(A) HKTA) HKTA,
|
||||
mmap func(HKTB, func(B) A) HKTA,
|
||||
fromio func(GIOB) HKTB,
|
||||
f func(A) GIOB) func(HKTA) HKTA {
|
||||
// chain
|
||||
return C.ChainFirst(mchain, mmap, F.Flow2(f, fromio))
|
||||
}
|
||||
|
||||
func MonadChainIOK[GR ~func() B, A, B, HKTA, HKTB any](
|
||||
mchain func(HKTA, func(A) HKTB) HKTB,
|
||||
fromio func(GR) HKTB,
|
||||
first HKTA, f func(A) GR) HKTB {
|
||||
// chain
|
||||
return C.MonadChain[A, B](mchain, first, F.Flow2(f, fromio))
|
||||
}
|
||||
|
||||
func ChainIOK[GR ~func() B, A, B, HKTA, HKTB any](
|
||||
mchain func(HKTA, func(A) HKTB) HKTB,
|
||||
fromio func(GR) HKTB,
|
||||
f func(A) GR) func(HKTA) HKTB {
|
||||
// chain
|
||||
return C.Chain[A, B](mchain, F.Flow2(f, fromio))
|
||||
}
|
11
internal/functor/functor.go
Normal file
11
internal/functor/functor.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package functor
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
)
|
||||
|
||||
// HKTFGA = HKT[F, HKT[G, A]]
|
||||
// HKTFGB = HKT[F, HKT[G, B]]
|
||||
func MonadMap[A, B, HKTGA, HKTGB, HKTFGA, HKTFGB any](fmap func(HKTFGA, func(HKTGA) HKTGB) HKTFGB, gmap func(HKTGA, func(A) B) HKTGB, fa HKTFGA, f func(A) B) HKTFGB {
|
||||
return fmap(fa, F.Bind2nd(gmap, f))
|
||||
}
|
@@ -27,40 +27,41 @@ HKTB = HKT<B>
|
||||
HKTAB = HKT<func(A)B>
|
||||
*/
|
||||
func traverseWithIndex[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(MB) HKTRB,
|
||||
_map func(HKTRB, func(MB) func(B) MB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(MB) HKTRB,
|
||||
fmap func(func(MB) func(B) MB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
ta MA, f func(K, A) HKTB) HKTRB {
|
||||
// this function inserts a value into a map with a given key
|
||||
cb := F.Curry3(addKey[MB, K, B])
|
||||
mmap := F.Flow2(F.Curry3(addKey[MB, K, B]), fmap)
|
||||
|
||||
return ReduceWithIndex(ta, func(k K, r HKTRB, a A) HKTRB {
|
||||
return _ap(
|
||||
_map(r, cb(k)),
|
||||
f(k, a),
|
||||
return F.Pipe2(
|
||||
r,
|
||||
mmap(k),
|
||||
fap(f(k, a)),
|
||||
)
|
||||
}, _of(createEmpty[MB]()))
|
||||
}, fof(createEmpty[MB]()))
|
||||
}
|
||||
|
||||
func MonadTraverse[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(MB) HKTRB,
|
||||
_map func(HKTRB, func(MB) func(B) MB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(MB) HKTRB,
|
||||
fmap func(func(MB) func(B) MB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
r MA, f func(A) HKTB) HKTRB {
|
||||
return traverseWithIndex(_of, _map, _ap, r, F.Ignore1of2[K](f))
|
||||
return traverseWithIndex(fof, fmap, fap, r, F.Ignore1of2[K](f))
|
||||
}
|
||||
|
||||
func TraverseWithIndex[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(MB) HKTRB,
|
||||
_map func(HKTRB, func(MB) func(B) MB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(MB) HKTRB,
|
||||
fmap func(func(MB) func(B) MB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
f func(K, A) HKTB) func(MA) HKTRB {
|
||||
|
||||
return func(ma MA) HKTRB {
|
||||
return traverseWithIndex(_of, _map, _ap, ma, f)
|
||||
return traverseWithIndex(fof, fmap, fap, ma, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +70,14 @@ func TraverseWithIndex[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB
|
||||
// HKTAB = HKT<func(A)B>
|
||||
// HKTRB = HKT<MB>
|
||||
func Traverse[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB, HKTRB any](
|
||||
_of func(MB) HKTRB,
|
||||
_map func(HKTRB, func(MB) func(B) MB) HKTAB,
|
||||
_ap func(HKTAB, HKTB) HKTRB,
|
||||
fof func(MB) HKTRB,
|
||||
fmap func(func(MB) func(B) MB) func(HKTRB) HKTAB,
|
||||
fap func(HKTB) func(HKTAB) HKTRB,
|
||||
|
||||
f func(A) HKTB) func(MA) HKTRB {
|
||||
|
||||
return func(ma MA) HKTRB {
|
||||
return MonadTraverse(_of, _map, _ap, ma, f)
|
||||
return MonadTraverse(fof, fmap, fap, ma, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +85,10 @@ func Traverse[MA ~map[K]A, MB ~map[K]B, K comparable, A, B, HKTB, HKTAB, HKTRB a
|
||||
// HKTAA = HKT[func(A)MA]
|
||||
// HKTRA = HKT[MA]
|
||||
func Sequence[MA ~map[K]A, MKTA ~map[K]HKTA, K comparable, A, HKTA, HKTAA, HKTRA any](
|
||||
_of func(MA) HKTRA,
|
||||
_map func(HKTRA, func(MA) func(A) MA) HKTAA,
|
||||
_ap func(HKTAA, HKTA) HKTRA,
|
||||
fof func(MA) HKTRA,
|
||||
fmap func(func(MA) func(A) MA) func(HKTRA) HKTAA,
|
||||
fap func(HKTA) func(HKTAA) HKTRA,
|
||||
|
||||
ma MKTA) HKTRA {
|
||||
return MonadTraverse(_of, _map, _ap, ma, F.Identity[HKTA])
|
||||
return MonadTraverse(fof, fmap, fap, ma, F.Identity[HKTA])
|
||||
}
|
||||
|
15
io/apply.go
Normal file
15
io/apply.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
M "github.com/ibm/fp-go/monoid"
|
||||
S "github.com/ibm/fp-go/semigroup"
|
||||
)
|
||||
|
||||
func ApplySemigroup[A any](s S.Semigroup[A]) S.Semigroup[IO[A]] {
|
||||
return G.ApplySemigroup[IO[A]](s)
|
||||
}
|
||||
|
||||
func ApplicativeMonoid[A any](m M.Monoid[A]) M.Monoid[IO[A]] {
|
||||
return G.ApplicativeMonoid[IO[A]](m)
|
||||
}
|
11
io/eq.go
Normal file
11
io/eq.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IO monad
|
||||
func Eq[A any](e EQ.Eq[A]) EQ.Eq[IO[A]] {
|
||||
return G.Eq[IO[A]](e)
|
||||
}
|
81
io/generic/ap.go
Normal file
81
io/generic/ap.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/internal/apply"
|
||||
)
|
||||
|
||||
const (
|
||||
// useParallel is the feature flag to control if we use the parallel or the sequential implementation of ap
|
||||
useParallel = true
|
||||
)
|
||||
|
||||
// monadApSeq implements the applicative on a single thread by first executing mab and the ma
|
||||
func monadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
||||
return MakeIO[GB](func() B {
|
||||
return mab()(ma())
|
||||
})
|
||||
}
|
||||
|
||||
// monadApPar implements the applicative on two threads, the main thread executes mab and the actuall
|
||||
// apply operation and the second thred computes ma. Communication between the threads happens via a channel
|
||||
func monadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
||||
return MakeIO[GB](func() B {
|
||||
c := make(chan A)
|
||||
go func() {
|
||||
c <- ma()
|
||||
close(c)
|
||||
}()
|
||||
return mab()(<-c)
|
||||
})
|
||||
}
|
||||
|
||||
// MonadAp implements the `ap` operation. Depending on a feature flag this will be sequential or parallel, the preferred implementation
|
||||
// is parallel
|
||||
func MonadAp[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
||||
if useParallel {
|
||||
return monadApPar[GA, GB](mab, ma)
|
||||
}
|
||||
return monadApSeq[GA, GB](mab, ma)
|
||||
}
|
||||
|
||||
// MonadApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func MonadApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](first GA, second GB) GA {
|
||||
return G.MonadApFirst(
|
||||
MonadAp[GB, GA, GBA, B, A],
|
||||
MonadMap[GA, GBA, A, func(B) A],
|
||||
|
||||
first,
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// ApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func ApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](second GB) func(GA) GA {
|
||||
return G.ApFirst(
|
||||
MonadAp[GB, GA, GBA, B, A],
|
||||
MonadMap[GA, GBA, A, func(B) A],
|
||||
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// MonadApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func MonadApSecond[GA ~func() A, GB ~func() B, GBB ~func() func(B) B, A, B any](first GA, second GB) GB {
|
||||
return G.MonadApSecond(
|
||||
MonadAp[GB, GB, GBB, B, B],
|
||||
MonadMap[GA, GBB, A, func(B) B],
|
||||
|
||||
first,
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// ApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func ApSecond[GA ~func() A, GB ~func() B, GBB ~func() func(B) B, A, B any](second GB) func(GA) GB {
|
||||
return G.ApSecond(
|
||||
MonadAp[GB, GB, GBB, B, B],
|
||||
MonadMap[GA, GBB, A, func(B) B],
|
||||
|
||||
second,
|
||||
)
|
||||
}
|
14
io/generic/apply.go
Normal file
14
io/generic/apply.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
M "github.com/ibm/fp-go/monoid"
|
||||
S "github.com/ibm/fp-go/semigroup"
|
||||
)
|
||||
|
||||
func ApplySemigroup[GA ~func() A, A any](s S.Semigroup[A]) S.Semigroup[GA] {
|
||||
return S.ApplySemigroup(MonadMap[GA, func() func(A) A, A, func(A) A], MonadAp[GA, GA, func() func(A) A, A, A], s)
|
||||
}
|
||||
|
||||
func ApplicativeMonoid[GA ~func() A, A any](m M.Monoid[A]) M.Monoid[GA] {
|
||||
return M.ApplicativeMonoid(Of[GA, A], MonadMap[GA, func() func(A) A, A, func(A) A], MonadAp[GA, GA, func() func(A) A, A, A], m)
|
||||
}
|
20
io/generic/eq.go
Normal file
20
io/generic/eq.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/internal/eq"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IO monad
|
||||
func Eq[GA ~func() A, A any](e EQ.Eq[A]) EQ.Eq[GA] {
|
||||
// comparator for the monad
|
||||
eq := G.Eq(
|
||||
MonadMap[GA, func() func(A) bool, A, func(A) bool],
|
||||
MonadAp[GA, func() bool, func() func(A) bool, A, bool],
|
||||
e,
|
||||
)
|
||||
// eagerly execute
|
||||
return EQ.FromEquals(func(l, r GA) bool {
|
||||
return eq(l, r)()
|
||||
})
|
||||
}
|
133
io/generic/io.go
Normal file
133
io/generic/io.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
F "github.com/ibm/fp-go/function"
|
||||
C "github.com/ibm/fp-go/internal/chain"
|
||||
)
|
||||
|
||||
// type IO[A any] = func() A
|
||||
|
||||
func MakeIO[GA ~func() A, A any](f func() A) GA {
|
||||
return f
|
||||
}
|
||||
|
||||
func Of[GA ~func() A, A any](a A) GA {
|
||||
return MakeIO[GA](F.Constant(a))
|
||||
}
|
||||
|
||||
func FromIO[GA ~func() A, A any](a GA) GA {
|
||||
return a
|
||||
}
|
||||
|
||||
// FromImpure converts a side effect without a return value into a side effect that returns any
|
||||
func FromImpure[GA ~func() any, IMP ~func()](f IMP) GA {
|
||||
return MakeIO[GA](func() any {
|
||||
f()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func MonadOf[GA ~func() A, A any](a A) GA {
|
||||
return MakeIO[GA](F.Constant(a))
|
||||
}
|
||||
|
||||
func MonadMap[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) B) GB {
|
||||
return MakeIO[GB](func() B {
|
||||
return F.Pipe1(fa(), f)
|
||||
})
|
||||
}
|
||||
|
||||
func Map[GA ~func() A, GB ~func() B, A, B any](f func(A) B) func(GA) GB {
|
||||
return F.Bind2nd(MonadMap[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
func MonadMapTo[GA ~func() A, GB ~func() B, A, B any](fa GA, b B) GB {
|
||||
return MonadMap[GA, GB](fa, F.Constant1[A](b))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return MakeIO[GB](func() B {
|
||||
return F.Pipe1(fa(), f)()
|
||||
})
|
||||
}
|
||||
|
||||
// Chain composes computations in sequence, using the return value of one computation to determine the next computation.
|
||||
func Chain[GA ~func() A, GB ~func() B, A, B any](f func(A) GB) func(GA) GB {
|
||||
return F.Bind2nd(MonadChain[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
// MonadChainTo composes computations in sequence, ignoring the return value of the first computation
|
||||
func MonadChainTo[GA ~func() A, GB ~func() B, A, B any](fa GA, fb GB) GB {
|
||||
return MonadChain(fa, F.Constant1[A](fb))
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return F.Bind2nd(MonadChainTo[GA, GB, A, B], fb)
|
||||
}
|
||||
|
||||
// MonadChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and
|
||||
// keeping only the result of the first.
|
||||
func MonadChainFirst[GA ~func() A, GB ~func() B, A, B any](fa GA, f func(A) GB) GA {
|
||||
return C.MonadChainFirst(MonadChain[GA, GA, A, A], MonadMap[GB, GA, B, A], fa, f)
|
||||
}
|
||||
|
||||
// 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.
|
||||
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)
|
||||
}
|
||||
|
||||
func Ap[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](ma GA) func(GAB) GB {
|
||||
return F.Bind2nd(MonadAp[GA, GB, GAB, A, B], ma)
|
||||
}
|
||||
|
||||
func Flatten[GA ~func() A, GAA ~func() GA, A any](mma GAA) GA {
|
||||
return mma()
|
||||
}
|
||||
|
||||
// Memoize computes the value of the provided IO monad lazily but exactly once
|
||||
func Memoize[GA ~func() A, A any](ma GA) GA {
|
||||
// synchronization primitives
|
||||
var once sync.Once
|
||||
var result A
|
||||
// callback
|
||||
gen := func() {
|
||||
result = ma()
|
||||
}
|
||||
// returns our memoized wrapper
|
||||
return func() A {
|
||||
once.Do(gen)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// Delay creates an operation that passes in the value after some delay
|
||||
func Delay[GA ~func() A, A any](delay time.Duration) func(GA) GA {
|
||||
return func(ga GA) GA {
|
||||
return MakeIO[GA](func() A {
|
||||
time.Sleep(delay)
|
||||
return ga()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Now returns the current timestamp
|
||||
func Now[GA ~func() time.Time]() GA {
|
||||
return MakeIO[GA](time.Now)
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[GA ~func() A, A any](gen func() GA) GA {
|
||||
return MakeIO[GA](func() A {
|
||||
return gen()()
|
||||
})
|
||||
}
|
29
io/generic/logging.go
Normal file
29
io/generic/logging.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
Logging "github.com/ibm/fp-go/logging"
|
||||
)
|
||||
|
||||
func Logger[GA ~func() any, A any](loggers ...*log.Logger) func(string) func(A) GA {
|
||||
_, right := Logging.LoggingCallbacks(loggers...)
|
||||
return func(prefix string) func(A) GA {
|
||||
return func(a A) GA {
|
||||
return FromImpure[GA](func() {
|
||||
right("%s: %v", prefix, a)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Logf[GA ~func() any, A any](loggers ...*log.Logger) func(string) func(A) GA {
|
||||
_, right := Logging.LoggingCallbacks(loggers...)
|
||||
return func(prefix string) func(A) GA {
|
||||
return func(a A) GA {
|
||||
return FromImpure[GA](func() {
|
||||
right(prefix, a)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
34
io/generic/retry.go
Normal file
34
io/generic/retry.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
G "github.com/ibm/fp-go/retry/generic"
|
||||
)
|
||||
|
||||
type retryStatusIO = func() R.RetryStatus
|
||||
|
||||
// Retry combinator for actions that don't raise exceptions, but
|
||||
// signal in their type the outcome has failed. Examples are the
|
||||
// `Option`, `Either` and `EitherT` monads.
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
func Retrying[GA ~func() A, A any](
|
||||
policy R.RetryPolicy,
|
||||
action func(R.RetryStatus) GA,
|
||||
check func(A) bool,
|
||||
) GA {
|
||||
// get an implementation for the types
|
||||
return G.Retrying(
|
||||
Chain[GA, GA, A, A],
|
||||
Chain[retryStatusIO, GA, R.RetryStatus, A],
|
||||
Of[GA, A],
|
||||
Of[retryStatusIO, R.RetryStatus],
|
||||
Delay[retryStatusIO, R.RetryStatus],
|
||||
|
||||
policy,
|
||||
action,
|
||||
check,
|
||||
)
|
||||
}
|
45
io/generic/sequence.go
Normal file
45
io/generic/sequence.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"github.com/ibm/fp-go/internal/apply"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[GA ~func() A, GTA ~func() T.Tuple1[A], A any](a GA) GTA {
|
||||
return apply.SequenceT1(
|
||||
Map[GA, GTA, A, T.Tuple1[A]],
|
||||
a,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT2[GA ~func() A, GB ~func() B, GTAB ~func() T.Tuple2[A, B], A, B any](a GA, b GB) GTAB {
|
||||
return apply.SequenceT2(
|
||||
Map[GA, func() func(B) T.Tuple2[A, B], A, func(B) T.Tuple2[A, B]],
|
||||
Ap[GB, GTAB, func() func(B) T.Tuple2[A, B], B, T.Tuple2[A, B]],
|
||||
|
||||
a, b,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT3[GA ~func() A, GB ~func() B, GC ~func() C, GTABC ~func() T.Tuple3[A, B, C], A, B, C any](a GA, b GB, c GC) GTABC {
|
||||
return apply.SequenceT3(
|
||||
Map[GA, func() func(B) func(C) T.Tuple3[A, B, C], A, func(B) func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GB, func() func(C) T.Tuple3[A, B, C], func() func(B) func(C) T.Tuple3[A, B, C], B, func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GC, GTABC, func() func(C) T.Tuple3[A, B, C], C, T.Tuple3[A, B, C]],
|
||||
|
||||
a, b, c,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT4[GA ~func() A, GB ~func() B, GC ~func() C, GD ~func() D, GTABCD ~func() T.Tuple4[A, B, C, D], A, B, C, D any](a GA, b GB, c GC, d GD) GTABCD {
|
||||
return apply.SequenceT4(
|
||||
Map[GA, func() func(B) func(C) func(D) T.Tuple4[A, B, C, D], A, func(B) func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GB, func() func(C) func(D) T.Tuple4[A, B, C, D], func() func(B) func(C) func(D) T.Tuple4[A, B, C, D], B, func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GC, func() func(D) T.Tuple4[A, B, C, D], func() func(C) func(D) T.Tuple4[A, B, C, D], C, func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GD, GTABCD, func() func(D) T.Tuple4[A, B, C, D], D, T.Tuple4[A, B, C, D]],
|
||||
|
||||
a, b, c, d,
|
||||
)
|
||||
}
|
56
io/generic/traverse.go
Normal file
56
io/generic/traverse.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
F "github.com/ibm/fp-go/function"
|
||||
RA "github.com/ibm/fp-go/internal/array"
|
||||
RR "github.com/ibm/fp-go/internal/record"
|
||||
)
|
||||
|
||||
func MonadTraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
|
||||
return RA.MonadTraverse(
|
||||
Of[GBS, BBS],
|
||||
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() func(B) BBS, B, BBS],
|
||||
|
||||
tas,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
|
||||
return RA.Traverse[AAS](
|
||||
Of[GBS, BBS],
|
||||
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() func(B) BBS, B, BBS],
|
||||
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
|
||||
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
|
||||
}
|
||||
|
||||
// MonadTraverseRecord transforms a record using an IO transform an IO of a record
|
||||
func MonadTraverseRecord[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||
return RR.MonadTraverse[MA](
|
||||
Of[GBS, MB],
|
||||
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||
Ap[GB, GBS, func() func(B) MB, B, MB],
|
||||
ma, f,
|
||||
)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms a record using an IO transform an IO of a record
|
||||
func TraverseRecord[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
|
||||
return RR.Traverse[MA](
|
||||
Of[GBS, MB],
|
||||
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||
Ap[GB, GBS, func() func(B) MB, B, MB],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
||||
return MonadTraverseRecord[GA, GAS](tas, F.Identity[GA])
|
||||
}
|
125
io/io.go
Normal file
125
io/io.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
// IO represents a synchronous computation that cannot fail
|
||||
// refer to [https://andywhite.xyz/posts/2021-01-27-rte-foundations/#ioltagt] for more details
|
||||
type IO[A any] func() A
|
||||
|
||||
func MakeIO[A any](f func() A) IO[A] {
|
||||
return G.MakeIO[IO[A]](f)
|
||||
}
|
||||
|
||||
func Of[A any](a A) IO[A] {
|
||||
return G.Of[IO[A]](a)
|
||||
}
|
||||
|
||||
func FromIO[A any](a IO[A]) IO[A] {
|
||||
return G.FromIO(a)
|
||||
}
|
||||
|
||||
// FromImpure converts a side effect without a return value into a side effect that returns any
|
||||
func FromImpure(f func()) IO[any] {
|
||||
return G.FromImpure[IO[any]](f)
|
||||
}
|
||||
|
||||
func MonadOf[A any](a A) IO[A] {
|
||||
return G.MonadOf[IO[A]](a)
|
||||
}
|
||||
|
||||
func MonadMap[A, B any](fa IO[A], f func(A) B) IO[B] {
|
||||
return G.MonadMap[IO[A], IO[B]](fa, f)
|
||||
}
|
||||
|
||||
func Map[A, B any](f func(A) B) func(fa IO[A]) IO[B] {
|
||||
return G.Map[IO[A], IO[B]](f)
|
||||
}
|
||||
|
||||
func MonadMapTo[A, B any](fa IO[A], b B) IO[B] {
|
||||
return G.MonadMapTo[IO[A], IO[B]](fa, b)
|
||||
}
|
||||
|
||||
func MapTo[A, B any](b B) func(IO[A]) IO[B] {
|
||||
return G.MapTo[IO[A], IO[B]](b)
|
||||
}
|
||||
|
||||
// MonadChain composes computations in sequence, using the return value of one computation to determine the next computation.
|
||||
func MonadChain[A, B any](fa IO[A], f func(A) IO[B]) IO[B] {
|
||||
return G.MonadChain(fa, f)
|
||||
}
|
||||
|
||||
// Chain composes computations in sequence, using the return value of one computation to determine the next computation.
|
||||
func Chain[A, B any](f func(A) IO[B]) func(IO[A]) IO[B] {
|
||||
return G.Chain[IO[A]](f)
|
||||
}
|
||||
|
||||
func MonadAp[B, A any](mab IO[func(A) B], ma IO[A]) IO[B] {
|
||||
return G.MonadAp[IO[A], IO[B]](mab, ma)
|
||||
}
|
||||
|
||||
func Ap[B, A any](ma IO[A]) func(IO[func(A) B]) IO[B] {
|
||||
return G.Ap[IO[A], IO[B], IO[func(A) B]](ma)
|
||||
}
|
||||
|
||||
func Flatten[A any](mma IO[IO[A]]) IO[A] {
|
||||
return G.Flatten(mma)
|
||||
}
|
||||
|
||||
// Memoize computes the value of the provided IO monad lazily but exactly once
|
||||
func Memoize[A any](ma IO[A]) IO[A] {
|
||||
return G.Memoize(ma)
|
||||
}
|
||||
|
||||
// MonadChainFirst composes computations in sequence, using the return value of one computation to determine the next computation and
|
||||
// keeping only the result of the first.
|
||||
func MonadChainFirst[A, B any](fa IO[A], f func(A) IO[B]) IO[A] {
|
||||
return G.MonadChainFirst(fa, f)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func ChainFirst[A, B any](f func(A) IO[B]) func(IO[A]) IO[A] {
|
||||
return G.ChainFirst[IO[A]](f)
|
||||
}
|
||||
|
||||
// MonadApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func MonadApFirst[A, B any](first IO[A], second IO[B]) IO[A] {
|
||||
return G.MonadApFirst[IO[A], IO[B], IO[func(B) A]](first, second)
|
||||
}
|
||||
|
||||
// ApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func ApFirst[A, B any](second IO[B]) func(IO[A]) IO[A] {
|
||||
return G.ApFirst[IO[A], IO[B], IO[func(B) A]](second)
|
||||
}
|
||||
|
||||
// MonadApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func MonadApSecond[A, B any](first IO[A], second IO[B]) IO[B] {
|
||||
return G.MonadApSecond[IO[A], IO[B], IO[func(B) B]](first, second)
|
||||
}
|
||||
|
||||
// ApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func ApSecond[A, B any](second IO[B]) func(IO[A]) IO[B] {
|
||||
return G.ApSecond[IO[A], IO[B], IO[func(B) B]](second)
|
||||
}
|
||||
|
||||
// MonadChainTo composes computations in sequence, ignoring the return value of the first computation
|
||||
func MonadChainTo[A, B any](fa IO[A], fb IO[B]) IO[B] {
|
||||
return G.MonadChainTo(fa, fb)
|
||||
}
|
||||
|
||||
// ChainTo composes computations in sequence, ignoring the return value of the first computation
|
||||
func ChainTo[A, B any](fb IO[B]) func(IO[A]) IO[B] {
|
||||
return G.ChainTo[IO[A]](fb)
|
||||
}
|
||||
|
||||
// Now returns the current timestamp
|
||||
var Now = G.Now[IO[time.Time]]()
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[A any](gen func() IO[A]) IO[A] {
|
||||
return G.Defer[IO[A]](gen)
|
||||
}
|
58
io/io_test.go
Normal file
58
io/io_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/ibm/fp-go/internal/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
assert.Equal(t, 2, F.Pipe1(Of(1), Map(utils.Double))())
|
||||
}
|
||||
|
||||
func TestChain(t *testing.T) {
|
||||
f := func(n int) IO[int] {
|
||||
return Of(n * 2)
|
||||
}
|
||||
assert.Equal(t, 2, F.Pipe1(Of(1), Chain(f))())
|
||||
}
|
||||
|
||||
func TestAp(t *testing.T) {
|
||||
assert.Equal(t, 2, F.Pipe1(Of(utils.Double), Ap[int, int](Of(1)))())
|
||||
}
|
||||
|
||||
func TestFlatten(t *testing.T) {
|
||||
assert.Equal(t, 1, F.Pipe1(Of(Of(1)), Flatten[int])())
|
||||
}
|
||||
|
||||
func TestMemoize(t *testing.T) {
|
||||
data := Memoize(MakeIO(rand.Int))
|
||||
|
||||
value1 := data()
|
||||
value2 := data()
|
||||
|
||||
assert.Equal(t, value1, value2)
|
||||
}
|
||||
|
||||
func TestApFirst(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of("a"),
|
||||
ApFirst[string](Of("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, "a", x())
|
||||
}
|
||||
|
||||
func TestApSecond(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of("a"),
|
||||
ApSecond[string](Of("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, "b", x())
|
||||
}
|
18
io/logging.go
Normal file
18
io/logging.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
// Logger constructs a logger function that can be used with ChainXXXIOK
|
||||
func Logger[A any](loggers ...*log.Logger) func(string) func(A) IO[any] {
|
||||
return G.Logger[IO[any], A](loggers...)
|
||||
}
|
||||
|
||||
// Logf constructs a logger function that can be used with ChainXXXIOK
|
||||
// the string prefix contains the format string for the log value
|
||||
func Logf[A any](loggers ...*log.Logger) func(string) func(A) IO[any] {
|
||||
return G.Logf[IO[any], A](loggers...)
|
||||
}
|
25
io/logging_test.go
Normal file
25
io/logging_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
|
||||
l := Logger[int]()
|
||||
|
||||
lio := l("out")
|
||||
|
||||
assert.Equal(t, nil, lio(10)())
|
||||
}
|
||||
|
||||
func TestLogf(t *testing.T) {
|
||||
|
||||
l := Logf[int]()
|
||||
|
||||
lio := l("Value is %d")
|
||||
|
||||
assert.Equal(t, nil, lio(10)())
|
||||
}
|
19
io/retry.go
Normal file
19
io/retry.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
)
|
||||
|
||||
// Retrying will retry the actions according to the check policy
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
func Retrying[A any](
|
||||
policy R.RetryPolicy,
|
||||
action func(R.RetryStatus) IO[A],
|
||||
check func(A) bool,
|
||||
) IO[A] {
|
||||
return G.Retrying(policy, action, check)
|
||||
}
|
32
io/retry_test.go
Normal file
32
io/retry_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var expLogBackoff = R.ExponentialBackoff(10)
|
||||
|
||||
// our retry policy with a 1s cap
|
||||
var testLogPolicy = R.CapDelay(
|
||||
2*time.Second,
|
||||
R.Monoid.Concat(expLogBackoff, R.LimitRetries(20)),
|
||||
)
|
||||
|
||||
func TestRetry(t *testing.T) {
|
||||
action := func(status R.RetryStatus) IO[string] {
|
||||
return Of(fmt.Sprintf("Retrying %d", status.IterNumber))
|
||||
}
|
||||
check := func(value string) bool {
|
||||
return !strings.Contains(value, "5")
|
||||
}
|
||||
|
||||
r := Retrying(testLogPolicy, action, check)
|
||||
|
||||
assert.Equal(t, "Retrying 5", r())
|
||||
}
|
24
io/sequence.go
Normal file
24
io/sequence.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[A any](a IO[A]) IO[T.Tuple1[A]] {
|
||||
return G.SequenceT1[IO[A], IO[T.Tuple1[A]]](a)
|
||||
}
|
||||
|
||||
func SequenceT2[A, B any](a IO[A], b IO[B]) IO[T.Tuple2[A, B]] {
|
||||
return G.SequenceT2[IO[A], IO[B], IO[T.Tuple2[A, B]]](a, b)
|
||||
}
|
||||
|
||||
func SequenceT3[A, B, C any](a IO[A], b IO[B], c IO[C]) IO[T.Tuple3[A, B, C]] {
|
||||
return G.SequenceT3[IO[A], IO[B], IO[C], IO[T.Tuple3[A, B, C]]](a, b, c)
|
||||
}
|
||||
|
||||
func SequenceT4[A, B, C, D any](a IO[A], b IO[B], c IO[C], d IO[D]) IO[T.Tuple4[A, B, C, D]] {
|
||||
return G.SequenceT4[IO[A], IO[B], IO[C], IO[D], IO[T.Tuple4[A, B, C, D]]](a, b, c, d)
|
||||
}
|
59
io/testing/laws.go
Normal file
59
io/testing/laws.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
L "github.com/ibm/fp-go/internal/monad/testing"
|
||||
"github.com/ibm/fp-go/io"
|
||||
)
|
||||
|
||||
// AssertLaws asserts the apply monad laws for the `Either` monad
|
||||
func AssertLaws[A, B, C any](t *testing.T,
|
||||
eqa EQ.Eq[A],
|
||||
eqb EQ.Eq[B],
|
||||
eqc EQ.Eq[C],
|
||||
|
||||
ab func(A) B,
|
||||
bc func(B) C,
|
||||
) func(a A) bool {
|
||||
|
||||
return L.AssertLaws(t,
|
||||
io.Eq(eqa),
|
||||
io.Eq(eqb),
|
||||
io.Eq(eqc),
|
||||
|
||||
io.Of[A],
|
||||
io.Of[B],
|
||||
io.Of[C],
|
||||
|
||||
io.Of[func(A) A],
|
||||
io.Of[func(A) B],
|
||||
io.Of[func(B) C],
|
||||
io.Of[func(func(A) B) B],
|
||||
|
||||
io.MonadMap[A, A],
|
||||
io.MonadMap[A, B],
|
||||
io.MonadMap[A, C],
|
||||
io.MonadMap[B, C],
|
||||
|
||||
io.MonadMap[func(B) C, func(func(A) B) func(A) C],
|
||||
|
||||
io.MonadChain[A, A],
|
||||
io.MonadChain[A, B],
|
||||
io.MonadChain[A, C],
|
||||
io.MonadChain[B, C],
|
||||
|
||||
io.MonadAp[A, A],
|
||||
io.MonadAp[B, A],
|
||||
io.MonadAp[C, B],
|
||||
io.MonadAp[C, A],
|
||||
|
||||
io.MonadAp[B, func(A) B],
|
||||
io.MonadAp[func(A) C, func(A) B],
|
||||
|
||||
ab,
|
||||
bc,
|
||||
)
|
||||
|
||||
}
|
32
io/testing/laws_test.go
Normal file
32
io/testing/laws_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMonadLaws(t *testing.T) {
|
||||
// some comparison
|
||||
eqa := EQ.FromStrictEquals[bool]()
|
||||
eqb := EQ.FromStrictEquals[int]()
|
||||
eqc := EQ.FromStrictEquals[string]()
|
||||
|
||||
ab := func(a bool) int {
|
||||
if a {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
bc := func(b int) string {
|
||||
return fmt.Sprintf("value %d", b)
|
||||
}
|
||||
|
||||
laws := AssertLaws(t, eqa, eqb, eqc, ab, bc)
|
||||
|
||||
assert.True(t, laws(true))
|
||||
assert.True(t, laws(false))
|
||||
}
|
35
io/traverse.go
Normal file
35
io/traverse.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package io
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
func MonadTraverseArray[A, B any](tas []A, f func(A) IO[B]) IO[[]B] {
|
||||
return G.MonadTraverseArray[IO[B], IO[[]B]](tas, f)
|
||||
}
|
||||
|
||||
// TraverseArray applies a function returning an [IO] to all elements in an array and the
|
||||
// transforms this into an [IO] of that array
|
||||
func TraverseArray[A, B any](f func(A) IO[B]) func([]A) IO[[]B] {
|
||||
return G.TraverseArray[IO[B], IO[[]B], []A](f)
|
||||
}
|
||||
|
||||
// SequenceArray converts an array of [IO] to an [IO] of an array
|
||||
func SequenceArray[A any](tas []IO[A]) IO[[]A] {
|
||||
return G.SequenceArray[IO[A], IO[[]A]](tas)
|
||||
}
|
||||
|
||||
func MonadTraverseRecord[K comparable, A, B any](tas map[K]A, f func(A) IO[B]) IO[map[K]B] {
|
||||
return G.MonadTraverseRecord[IO[B], IO[map[K]B]](tas, f)
|
||||
}
|
||||
|
||||
// TraverseArray applies a function returning an [IO] to all elements in a record and the
|
||||
// transforms this into an [IO] of that record
|
||||
func TraverseRecord[K comparable, A, B any](f func(A) IO[B]) func(map[K]A) IO[map[K]B] {
|
||||
return G.TraverseRecord[IO[B], IO[map[K]B], map[K]A](f)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a record of [IO] to an [IO] of a record
|
||||
func SequenceRecord[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
|
||||
return G.SequenceRecord[IO[A], IO[map[K]A]](tas)
|
||||
}
|
25
ioeither/ap.go
Normal file
25
ioeither/ap.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
// MonadApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func MonadApFirst[E, A, B any](first IOEither[E, A], second IOEither[E, B]) IOEither[E, A] {
|
||||
return G.MonadApFirst[IOEither[E, A], IOEither[E, B], IOEither[E, func(B) A]](first, second)
|
||||
}
|
||||
|
||||
// ApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func ApFirst[E, A, B any](second IOEither[E, B]) func(IOEither[E, A]) IOEither[E, A] {
|
||||
return G.ApFirst[IOEither[E, A], IOEither[E, B], IOEither[E, func(B) A]](second)
|
||||
}
|
||||
|
||||
// MonadApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func MonadApSecond[E, A, B any](first IOEither[E, A], second IOEither[E, B]) IOEither[E, B] {
|
||||
return G.MonadApSecond[IOEither[E, A], IOEither[E, B], IOEither[E, func(B) B]](first, second)
|
||||
}
|
||||
|
||||
// ApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func ApSecond[E, A, B any](second IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ApSecond[IOEither[E, A], IOEither[E, B], IOEither[E, func(B) B]](second)
|
||||
}
|
16
ioeither/bracket.go
Normal file
16
ioeither/bracket.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||
// whether the body action returns and error or not.
|
||||
func Bracket[E, A, B, ANY any](
|
||||
acquire IOEither[E, A],
|
||||
use func(A) IOEither[E, B],
|
||||
release func(A, ET.Either[E, B]) IOEither[E, ANY],
|
||||
) IOEither[E, B] {
|
||||
return G.Bracket(acquire, use, release)
|
||||
}
|
17
ioeither/eq.go
Normal file
17
ioeither/eq.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IOEither monad
|
||||
func Eq[E, A any](eq EQ.Eq[ET.Either[E, A]]) EQ.Eq[IOEither[E, A]] {
|
||||
return G.Eq[IOEither[E, A]](eq)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||
func FromStrictEquals[E, A comparable]() EQ.Eq[IOEither[E, A]] {
|
||||
return G.FromStrictEquals[IOEither[E, A]]()
|
||||
}
|
30
ioeither/eq_test.go
Normal file
30
ioeither/eq_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEq(t *testing.T) {
|
||||
|
||||
r1 := Of[string](1)
|
||||
r2 := Of[string](1)
|
||||
r3 := Of[string](2)
|
||||
|
||||
e1 := Left[int]("a")
|
||||
e2 := Left[int]("a")
|
||||
e3 := Left[int]("b")
|
||||
|
||||
eq := FromStrictEquals[string, int]()
|
||||
|
||||
assert.True(t, eq.Equals(r1, r1))
|
||||
assert.True(t, eq.Equals(r1, r2))
|
||||
assert.False(t, eq.Equals(r1, r3))
|
||||
assert.False(t, eq.Equals(r1, e1))
|
||||
|
||||
assert.True(t, eq.Equals(e1, e1))
|
||||
assert.True(t, eq.Equals(e1, e2))
|
||||
assert.False(t, eq.Equals(e1, e3))
|
||||
assert.False(t, eq.Equals(e2, r2))
|
||||
}
|
13
ioeither/exec/exec.go
Normal file
13
ioeither/exec/exec.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"github.com/ibm/fp-go/exec"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
var (
|
||||
// Command executes a command
|
||||
Command = F.Curry3(G.Command[IOE.IOEither[error, exec.CommandOutput]])
|
||||
)
|
28
ioeither/exec/exec_test.go
Normal file
28
ioeither/exec/exec_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
RA "github.com/ibm/fp-go/array"
|
||||
B "github.com/ibm/fp-go/bytes"
|
||||
E "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/exec"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOpenSSL(t *testing.T) {
|
||||
// execute the openSSL binary
|
||||
version := F.Pipe1(
|
||||
Command("openssl")(RA.From("version"))(B.Monoid.Empty()),
|
||||
IOE.Map[error](F.Flow3(
|
||||
exec.StdOut,
|
||||
B.ToString,
|
||||
strings.TrimSpace,
|
||||
)),
|
||||
)
|
||||
|
||||
assert.True(t, E.IsRight(version()))
|
||||
}
|
13
ioeither/file/close.go
Normal file
13
ioeither/file/close.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
)
|
||||
|
||||
func onClose[R io.Closer](r R) IOE.IOEither[error, R] {
|
||||
return IOE.TryCatchError(func() (R, error) {
|
||||
return r, r.Close()
|
||||
})
|
||||
}
|
22
ioeither/file/file.go
Normal file
22
ioeither/file/file.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
)
|
||||
|
||||
var (
|
||||
// Open opens a file for reading
|
||||
Open = IOE.Eitherize1(os.Open)
|
||||
// ReadFile reads the context of a file
|
||||
ReadFile = IOE.Eitherize1(os.ReadFile)
|
||||
// WriteFile writes a data blob to a file
|
||||
WriteFile = func(dstName string, perm os.FileMode) func([]byte) IOE.IOEither[error, []byte] {
|
||||
return func(data []byte) IOE.IOEither[error, []byte] {
|
||||
return IOE.TryCatchError(func() ([]byte, error) {
|
||||
return data, os.WriteFile(dstName, data, perm)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
22
ioeither/file/readall.go
Normal file
22
ioeither/file/readall.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
)
|
||||
|
||||
func onReadAll[R io.Reader](r R) IOE.IOEither[error, []byte] {
|
||||
return IOE.TryCatchError(func() ([]byte, error) {
|
||||
return io.ReadAll(r)
|
||||
})
|
||||
}
|
||||
|
||||
// ReadAll uses a generator function to create a stream, reads it and closes it
|
||||
func ReadAll[R io.ReadCloser](acquire IOE.IOEither[error, R]) IOE.IOEither[error, []byte] {
|
||||
return IOE.WithResource[error, R, []byte](
|
||||
acquire,
|
||||
onClose[R])(
|
||||
onReadAll[R],
|
||||
)
|
||||
}
|
35
ioeither/file/write.go
Normal file
35
ioeither/file/write.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
)
|
||||
|
||||
func onWriteAll[W io.Writer](data []byte) func(w W) IOE.IOEither[error, []byte] {
|
||||
return func(w W) IOE.IOEither[error, []byte] {
|
||||
return IOE.TryCatchError(func() ([]byte, error) {
|
||||
_, err := w.Write(data)
|
||||
return data, err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// WriteAll uses a generator function to create a stream, writes data to it and closes it
|
||||
func WriteAll[W io.WriteCloser](data []byte) func(acquire IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
||||
onWrite := onWriteAll[W](data)
|
||||
return func(onCreate IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
||||
return IOE.WithResource[error, W, []byte](
|
||||
onCreate,
|
||||
onClose[W])(
|
||||
onWrite,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Write uses a generator function to create a stream, writes data to it and closes it
|
||||
func Write[W io.WriteCloser, R any](acquire IOE.IOEither[error, W]) func(use func(W) IOE.IOEither[error, R]) IOE.IOEither[error, R] {
|
||||
return IOE.WithResource[error, W, R](
|
||||
acquire,
|
||||
onClose[W])
|
||||
}
|
48
ioeither/generic/ap.go
Normal file
48
ioeither/generic/ap.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/internal/apply"
|
||||
)
|
||||
|
||||
// MonadApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func MonadApFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GBA ~func() ET.Either[E, func(B) A], E, A, B any](first GA, second GB) GA {
|
||||
return G.MonadApFirst(
|
||||
MonadAp[GB, GA, GBA, E, B, A],
|
||||
MonadMap[GA, GBA, E, A, func(B) A],
|
||||
|
||||
first,
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// ApFirst combines two effectful actions, keeping only the result of the first.
|
||||
func ApFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GBA ~func() ET.Either[E, func(B) A], E, A, B any](second GB) func(GA) GA {
|
||||
return G.ApFirst(
|
||||
MonadAp[GB, GA, GBA, E, B, A],
|
||||
MonadMap[GA, GBA, E, A, func(B) A],
|
||||
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// MonadApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func MonadApSecond[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GBB ~func() ET.Either[E, func(B) B], E, A, B any](first GA, second GB) GB {
|
||||
return G.MonadApSecond(
|
||||
MonadAp[GB, GB, GBB, E, B, B],
|
||||
MonadMap[GA, GBB, E, A, func(B) B],
|
||||
|
||||
first,
|
||||
second,
|
||||
)
|
||||
}
|
||||
|
||||
// ApSecond combines two effectful actions, keeping only the result of the second.
|
||||
func ApSecond[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GBB ~func() ET.Either[E, func(B) B], E, A, B any](second GB) func(GA) GB {
|
||||
return G.ApSecond(
|
||||
MonadAp[GB, GB, GBB, E, B, B],
|
||||
MonadMap[GA, GBB, E, A, func(B) B],
|
||||
|
||||
second,
|
||||
)
|
||||
}
|
31
ioeither/generic/bracket.go
Normal file
31
ioeither/generic/bracket.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/internal/file"
|
||||
I "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||
// whether the body action returns and error or not.
|
||||
func Bracket[
|
||||
GA ~func() ET.Either[E, A],
|
||||
GB ~func() ET.Either[E, B],
|
||||
GANY ~func() ET.Either[E, ANY],
|
||||
E, A, B, ANY any](
|
||||
|
||||
acquire GA,
|
||||
use func(A) GB,
|
||||
release func(A, ET.Either[E, B]) GANY,
|
||||
) GB {
|
||||
return G.Bracket[GA, GB, GANY, ET.Either[E, B], A, B](
|
||||
I.Of[GB, ET.Either[E, B]],
|
||||
MonadChain[GA, GB, E, A, B],
|
||||
I.MonadChain[GB, GB, ET.Either[E, B], ET.Either[E, B]],
|
||||
MonadChain[GANY, GB, E, ANY, B],
|
||||
|
||||
acquire,
|
||||
use,
|
||||
release,
|
||||
)
|
||||
}
|
17
ioeither/generic/eq.go
Normal file
17
ioeither/generic/eq.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/io/generic"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IOEither monad
|
||||
func Eq[GA ~func() ET.Either[E, A], E, A any](eq EQ.Eq[ET.Either[E, A]]) EQ.Eq[GA] {
|
||||
return G.Eq[GA](eq)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||
func FromStrictEquals[GA ~func() ET.Either[E, A], E, A comparable]() EQ.Eq[GA] {
|
||||
return Eq[GA](ET.FromStrictEquals[E, A]())
|
||||
}
|
16
ioeither/generic/exec.go
Normal file
16
ioeither/generic/exec.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/exec"
|
||||
GE "github.com/ibm/fp-go/internal/exec"
|
||||
)
|
||||
|
||||
// Command executes a command
|
||||
func Command[GA ~func() ET.Either[error, exec.CommandOutput]](name string, args []string, in []byte) GA {
|
||||
return TryCatchError[GA](func() (exec.CommandOutput, error) {
|
||||
return GE.Exec(context.Background(), name, args, in)
|
||||
})
|
||||
}
|
328
ioeither/generic/ioeither.go
Normal file
328
ioeither/generic/ioeither.go
Normal file
@@ -0,0 +1,328 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/errors"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
C "github.com/ibm/fp-go/internal/chain"
|
||||
"github.com/ibm/fp-go/internal/eithert"
|
||||
FE "github.com/ibm/fp-go/internal/fromeither"
|
||||
FI "github.com/ibm/fp-go/internal/fromio"
|
||||
IO "github.com/ibm/fp-go/io/generic"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
)
|
||||
|
||||
// type IOEither[E, A any] = func() Either[E, A]
|
||||
|
||||
func MakeIO[GA ~func() ET.Either[E, A], E, A any](f GA) GA {
|
||||
return f
|
||||
}
|
||||
|
||||
func Left[GA ~func() ET.Either[E, A], E, A any](l E) GA {
|
||||
return MakeIO(eithert.Left(IO.MonadOf[GA, ET.Either[E, A]], l))
|
||||
}
|
||||
|
||||
func Right[GA ~func() ET.Either[E, A], E, A any](r A) GA {
|
||||
return MakeIO(eithert.Right(IO.MonadOf[GA, ET.Either[E, A]], r))
|
||||
}
|
||||
|
||||
func Of[GA ~func() ET.Either[E, A], E, A any](r A) GA {
|
||||
return Right[GA](r)
|
||||
}
|
||||
|
||||
func MonadOf[GA ~func() ET.Either[E, A], E, A any](r A) GA {
|
||||
return Of[GA](r)
|
||||
}
|
||||
|
||||
func LeftIO[GA ~func() ET.Either[E, A], GE ~func() E, E, A any](ml GE) GA {
|
||||
return MakeIO(eithert.LeftF(IO.MonadMap[GE, GA, E, ET.Either[E, A]], ml))
|
||||
}
|
||||
|
||||
func RightIO[GA ~func() ET.Either[E, A], GR ~func() A, E, A any](mr GR) GA {
|
||||
return MakeIO(eithert.RightF(IO.MonadMap[GR, GA, A, ET.Either[E, A]], mr))
|
||||
}
|
||||
|
||||
func FromEither[GA ~func() ET.Either[E, A], E, A any](e ET.Either[E, A]) GA {
|
||||
return IO.Of[GA](e)
|
||||
}
|
||||
|
||||
func FromOption[GA ~func() ET.Either[E, A], E, A any](onNone func() E) func(o O.Option[A]) GA {
|
||||
return FE.FromOption(
|
||||
FromEither[GA, E, A],
|
||||
onNone,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainOptionK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](onNone func() E) func(func(A) O.Option[B]) func(GA) GB {
|
||||
return FE.ChainOptionK(
|
||||
MonadChain[GA, GB, E, A, B],
|
||||
FromEither[GB, E, B],
|
||||
onNone,
|
||||
)
|
||||
}
|
||||
|
||||
func FromIO[GA ~func() ET.Either[E, A], GR ~func() A, E, A any](mr GR) GA {
|
||||
return RightIO[GA](mr)
|
||||
}
|
||||
|
||||
func MonadMap[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, f func(A) B) GB {
|
||||
return eithert.MonadMap(IO.MonadMap[GA, GB, ET.Either[E, A], ET.Either[E, B]], fa, f)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func MonadMapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, b B) GB {
|
||||
return MonadMap[GA, GB](fa, F.Constant1[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 {
|
||||
return F.Bind2nd(MonadMapTo[GA, GB, E, A, B], 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 {
|
||||
return eithert.MonadChain(IO.MonadChain[GA, GB, ET.Either[E, A], ET.Either[E, B]], IO.MonadOf[GB, ET.Either[E, B]], fa, f)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func MonadChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, fb GB) GB {
|
||||
return MonadChain(fa, F.Constant1[A](fb))
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
return FE.MonadChainEitherK(
|
||||
MonadChain[GA, GB, E, A, B],
|
||||
FromEither[GB, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func MonadChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func() B, E, A, B any](ma GA, f func(A) GR) GB {
|
||||
return FI.MonadChainIOK(
|
||||
MonadChain[GA, GB, E, A, B],
|
||||
FromIO[GB, GR, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func() B, E, A, B any](f func(A) GR) func(GA) GB {
|
||||
return FI.ChainIOK(
|
||||
MonadChain[GA, GB, E, A, B],
|
||||
FromIO[GB, GR, E, B],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func MonadAp[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], E, A, B any](mab GAB, ma GA) GB {
|
||||
return eithert.MonadAp(
|
||||
IO.MonadAp[GA, GB, func() func(ET.Either[E, A]) ET.Either[E, B], ET.Either[E, A], ET.Either[E, B]],
|
||||
IO.MonadMap[GAB, func() func(ET.Either[E, A]) ET.Either[E, B], ET.Either[E, func(A) B], func(ET.Either[E, A]) ET.Either[E, B]],
|
||||
mab, ma)
|
||||
}
|
||||
|
||||
func Ap[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], E, A, B any](ma GA) func(GAB) GB {
|
||||
return F.Bind2nd(MonadAp[GA, GB, GAB, E, A, B], ma)
|
||||
}
|
||||
|
||||
func Flatten[GA ~func() ET.Either[E, A], GAA ~func() ET.Either[E, GA], E, A any](mma GAA) GA {
|
||||
return MonadChain(mma, F.Identity[GA])
|
||||
}
|
||||
|
||||
func TryCatch[GA ~func() ET.Either[E, A], E, A any](f func() (A, error), onThrow func(error) E) GA {
|
||||
return MakeIO(func() ET.Either[E, A] {
|
||||
return ET.TryCatch(f, onThrow)
|
||||
})
|
||||
}
|
||||
|
||||
func TryCatchError[GA ~func() ET.Either[error, A], A any](f func() (A, error)) GA {
|
||||
return TryCatch[GA](f, errors.IdentityError)
|
||||
}
|
||||
|
||||
func Eitherize0[GEA ~func() ET.Either[error, A], GA ~func() (A, error), A any](f GA) func() GEA {
|
||||
ef := ET.Eitherize0(f)
|
||||
return func() GEA {
|
||||
return MakeIO(ef)
|
||||
}
|
||||
}
|
||||
|
||||
func Uneitherize0[GEA ~func() ET.Either[error, A], GTA ~func() GEA, A any](f GTA) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return ET.Unwrap(f()())
|
||||
}
|
||||
}
|
||||
|
||||
func Eitherize1[GEA ~func() ET.Either[error, A], GA ~func(t1 T1) (A, error), T1, A any](f GA) func(T1) GEA {
|
||||
ef := ET.Eitherize1(f)
|
||||
return func(t1 T1) GEA {
|
||||
return MakeIO[GEA](func() ET.Either[error, A] {
|
||||
return ef(t1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Uneitherize1[GEA ~func() ET.Either[error, A], GTA ~func(t1 T1) GEA, T1, A any](f GTA) func(T1) (A, error) {
|
||||
return func(t1 T1) (A, error) {
|
||||
return ET.Unwrap(f(t1)())
|
||||
}
|
||||
}
|
||||
|
||||
func Eitherize2[GEA ~func() ET.Either[error, A], GA ~func(t1 T1, t2 T2) (A, error), T1, T2, A any](f GA) func(T1, T2) GEA {
|
||||
ef := ET.Eitherize2(f)
|
||||
return func(t1 T1, t2 T2) GEA {
|
||||
return MakeIO[GEA](func() ET.Either[error, A] {
|
||||
return ef(t1, t2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Uneitherize2[GEA ~func() ET.Either[error, A], GTA ~func(t1 T1, t2 T2) GEA, T1, T2, A any](f GTA) func(T1, T2) (A, error) {
|
||||
return func(t1 T1, t2 T2) (A, error) {
|
||||
return ET.Unwrap(f(t1, t2)())
|
||||
}
|
||||
}
|
||||
|
||||
func Eitherize3[GEA ~func() ET.Either[error, A], GA ~func(t1 T1, t2 T2, t3 T3) (A, error), T1, T2, T3, A any](f GA) func(T1, T2, T3) GEA {
|
||||
ef := ET.Eitherize3(f)
|
||||
return func(t1 T1, t2 T2, t3 T3) GEA {
|
||||
return MakeIO[GEA](func() ET.Either[error, A] {
|
||||
return ef(t1, t2, t3)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Uneitherize3[GEA ~func() ET.Either[error, A], GTA ~func(t1 T1, t2 T2, t3 T3) GEA, T1, T2, T3, A any](f GTA) func(T1, T2, T3) (A, error) {
|
||||
return func(t1 T1, t2 T2, t3 T3) (A, error) {
|
||||
return ET.Unwrap(f(t1, t2, t3)())
|
||||
}
|
||||
}
|
||||
|
||||
func Eitherize4[GEA ~func() ET.Either[error, A], GA ~func(t1 T1, t2 T2, t3 T3, t4 T4) (A, error), T1, T2, T3, T4, A any](f GA) func(T1, T2, T3, T4) GEA {
|
||||
ef := ET.Eitherize4(f)
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) GEA {
|
||||
return MakeIO[GEA](func() ET.Either[error, A] {
|
||||
return ef(t1, t2, t3, t4)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Uneitherize4[GEA ~func() ET.Either[error, A], GTA ~func(t1 T1, t2 T2, t3 T3, t4 T4) GEA, T1, T2, T3, T4, A any](f GTA) func(T1, T2, T3, T4) (A, error) {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) (A, error) {
|
||||
return ET.Unwrap(f(t1, t2, t3, t4)())
|
||||
}
|
||||
}
|
||||
|
||||
// Memoize computes the value of the provided IO monad lazily but exactly once
|
||||
func Memoize[GA ~func() ET.Either[E, A], E, A any](ma GA) GA {
|
||||
return IO.Memoize(ma)
|
||||
}
|
||||
|
||||
func MonadMapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2, A any](fa GA1, f func(E1) E2) GA2 {
|
||||
return eithert.MonadMapLeft(IO.MonadMap[GA1, GA2, ET.Either[E1, A], ET.Either[E2, A]], fa, f)
|
||||
}
|
||||
|
||||
func MapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2, A any](f func(E1) E2) func(GA1) GA2 {
|
||||
return F.Bind2nd(MonadMapLeft[GA1, GA2, E1, E2, A], f)
|
||||
}
|
||||
|
||||
// Delay creates an operation that passes in the value after some delay
|
||||
func Delay[GA ~func() ET.Either[E, A], E, A any](delay time.Duration) func(GA) GA {
|
||||
return IO.Delay[GA](delay)
|
||||
}
|
||||
|
||||
func MonadBiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](fa GA, f func(E1) E2, g func(A) B) GB {
|
||||
return eithert.MonadBiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], fa, f, g)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return eithert.BiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], f, g)
|
||||
}
|
||||
|
||||
// Fold convers an IOEither into an IO
|
||||
func Fold[GA ~func() ET.Either[E, A], GB ~func() B, E, A, B any](onLeft func(E) GB, onRight func(A) GB) func(GA) GB {
|
||||
return eithert.MatchE(IO.MonadChain[GA, GB, ET.Either[E, A], B], onLeft, onRight)
|
||||
}
|
||||
|
||||
func MonadFold[GA ~func() ET.Either[E, A], GB ~func() B, E, A, B any](ma GA, onLeft func(E) GB, onRight func(A) GB) GB {
|
||||
return eithert.FoldE(IO.MonadChain[GA, GB, ET.Either[E, A], B], ma, onLeft, onRight)
|
||||
}
|
||||
|
||||
// GetOrElse extracts the value or maps the error
|
||||
func GetOrElse[GA ~func() ET.Either[E, A], GB ~func() A, E, A any](onLeft func(E) GB) func(GA) GB {
|
||||
return eithert.GetOrElse(IO.MonadChain[GA, GB, ET.Either[E, A], A], IO.MonadOf[GB, A], onLeft)
|
||||
}
|
||||
|
||||
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](ma GA, f func(A) GB) GA {
|
||||
return C.MonadChainFirst(
|
||||
MonadChain[GA, GA, E, A, A],
|
||||
MonadMap[GB, GA, E, B, A],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return C.ChainFirst(
|
||||
MonadChain[GA, GA, E, A, A],
|
||||
MonadMap[GB, GA, E, B, A],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](first GA, f func(A) GIOB) GA {
|
||||
return FI.MonadChainFirstIOK(
|
||||
MonadChain[GA, GA, E, A, A],
|
||||
MonadMap[func() ET.Either[E, B], GA, E, B, A],
|
||||
FromIO[func() ET.Either[E, B], GIOB, E, B],
|
||||
first,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return FI.ChainFirstIOK(
|
||||
MonadChain[GA, GA, E, A, A],
|
||||
MonadMap[func() ET.Either[E, B], GA, E, B, A],
|
||||
FromIO[func() ET.Either[E, B], GIOB, E, B],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// Swap changes the order of type parameters
|
||||
func Swap[GEA ~func() ET.Either[E, A], GAE ~func() ET.Either[A, E], E, A any](val GEA) GAE {
|
||||
return MonadFold(val, Right[GAE], Left[GAE])
|
||||
}
|
||||
|
||||
// FromImpure converts a side effect without a return value into a side effect that returns any
|
||||
func FromImpure[GA ~func() ET.Either[E, any], IMP ~func(), E any](f IMP) GA {
|
||||
return F.Pipe2(
|
||||
f,
|
||||
IO.FromImpure[func() any, IMP],
|
||||
FromIO[GA, func() any],
|
||||
)
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[GEA ~func() ET.Either[E, A], E, A any](gen func() GEA) GEA {
|
||||
return IO.Defer[GEA](gen)
|
||||
}
|
22
ioeither/generic/resource.go
Normal file
22
ioeither/generic/resource.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
IF "github.com/ibm/fp-go/internal/file"
|
||||
)
|
||||
|
||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||
func WithResource[
|
||||
GA ~func() ET.Either[E, A],
|
||||
GR ~func() ET.Either[E, R],
|
||||
GANY ~func() ET.Either[E, ANY],
|
||||
E, R, A, ANY any](onCreate GR, onRelease func(R) GANY) func(func(R) GA) GA {
|
||||
return IF.WithResource(
|
||||
MonadChain[GR, GA, E, R, A],
|
||||
MonadFold[GA, GA, E, A, ET.Either[E, A]],
|
||||
MonadFold[GANY, GA, E, ANY, ET.Either[E, A]],
|
||||
MonadMap[GANY, GA, E, ANY, A],
|
||||
Left[GA, E, A],
|
||||
)(F.Constant(onCreate), onRelease)
|
||||
}
|
23
ioeither/generic/retry.go
Normal file
23
ioeither/generic/retry.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
GIO "github.com/ibm/fp-go/io/generic"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
)
|
||||
|
||||
// Retry combinator for actions that don't raise exceptions, but
|
||||
// signal in their type the outcome has failed. Examples are the
|
||||
// `Option`, `Either` and `EitherT` monads.
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
func Retrying[GA ~func() ET.Either[E, A], E, A any](
|
||||
policy R.RetryPolicy,
|
||||
action func(R.RetryStatus) GA,
|
||||
check func(ET.Either[E, A]) bool,
|
||||
) GA {
|
||||
// get an implementation for the types
|
||||
return GIO.Retrying(policy, action, check)
|
||||
}
|
47
ioeither/generic/sequence.go
Normal file
47
ioeither/generic/sequence.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/internal/apply"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[GA ~func() ET.Either[E, A], GTA ~func() ET.Either[E, T.Tuple1[A]], E, A any](a GA) GTA {
|
||||
return apply.SequenceT1(
|
||||
Map[GA, GTA, E, A, T.Tuple1[A]],
|
||||
|
||||
a,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT2[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GTAB ~func() ET.Either[E, T.Tuple2[A, B]], E, A, B any](a GA, b GB) GTAB {
|
||||
return apply.SequenceT2(
|
||||
Map[GA, func() ET.Either[E, func(B) T.Tuple2[A, B]], E, A, func(B) T.Tuple2[A, B]],
|
||||
Ap[GB, GTAB, func() ET.Either[E, func(B) T.Tuple2[A, B]], E, B, T.Tuple2[A, B]],
|
||||
|
||||
a, b,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT3[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GC ~func() ET.Either[E, C], GTABC ~func() ET.Either[E, T.Tuple3[A, B, C]], E, A, B, C any](a GA, b GB, c GC) GTABC {
|
||||
return apply.SequenceT3(
|
||||
Map[GA, func() ET.Either[E, func(B) func(C) T.Tuple3[A, B, C]], E, A, func(B) func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GB, func() ET.Either[E, func(C) T.Tuple3[A, B, C]], func() ET.Either[E, func(B) func(C) T.Tuple3[A, B, C]], E, B, func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GC, GTABC, func() ET.Either[E, func(C) T.Tuple3[A, B, C]], E, C, T.Tuple3[A, B, C]],
|
||||
|
||||
a, b, c,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT4[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GC ~func() ET.Either[E, C], GD ~func() ET.Either[E, D], GTABCD ~func() ET.Either[E, T.Tuple4[A, B, C, D]], E, A, B, C, D any](a GA, b GB, c GC, d GD) GTABCD {
|
||||
return apply.SequenceT4(
|
||||
Map[GA, func() ET.Either[E, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], E, A, func(B) func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GB, func() ET.Either[E, func(C) func(D) T.Tuple4[A, B, C, D]], func() ET.Either[E, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], E, B, func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GC, func() ET.Either[E, func(D) T.Tuple4[A, B, C, D]], func() ET.Either[E, func(C) func(D) T.Tuple4[A, B, C, D]], E, C, func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GD, GTABCD, func() ET.Either[E, func(D) T.Tuple4[A, B, C, D]], E, D, T.Tuple4[A, B, C, D]],
|
||||
|
||||
a, b, c, d,
|
||||
)
|
||||
}
|
64
ioeither/generic/traverse.go
Normal file
64
ioeither/generic/traverse.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
RA "github.com/ibm/fp-go/internal/array"
|
||||
RR "github.com/ibm/fp-go/internal/record"
|
||||
)
|
||||
|
||||
// MonadTraverseArray transforms an array
|
||||
func MonadTraverseArray[GB ~func() ET.Either[E, B], GBS ~func() ET.Either[E, BBS], AAS ~[]A, BBS ~[]B, E, A, B any](tas AAS, f func(A) GB) GBS {
|
||||
return RA.MonadTraverse[AAS](
|
||||
Of[GBS, E, BBS],
|
||||
Map[GBS, func() ET.Either[E, func(B) BBS], E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() ET.Either[E, func(B) BBS], E, B, BBS],
|
||||
|
||||
tas,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// TraverseArray transforms an array
|
||||
func TraverseArray[GB ~func() ET.Either[E, B], GBS ~func() ET.Either[E, BBS], AAS ~[]A, BBS ~[]B, E, A, B any](f func(A) GB) func(AAS) GBS {
|
||||
return RA.Traverse[AAS](
|
||||
Of[GBS, E, BBS],
|
||||
Map[GBS, func() ET.Either[E, func(B) BBS], E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() ET.Either[E, func(B) BBS], E, B, BBS],
|
||||
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceArray[GA ~func() ET.Either[E, A], GAS ~func() ET.Either[E, AAS], AAS ~[]A, GAAS ~[]GA, E, A any](tas GAAS) GAS {
|
||||
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
|
||||
}
|
||||
|
||||
// MonadTraverseRecord transforms an array
|
||||
func MonadTraverseRecord[GB ~func() ET.Either[E, B], GBS ~func() ET.Either[E, BBS], AAS ~map[K]A, BBS ~map[K]B, K comparable, E, A, B any](tas AAS, f func(A) GB) GBS {
|
||||
return RR.MonadTraverse[AAS](
|
||||
Of[GBS, E, BBS],
|
||||
Map[GBS, func() ET.Either[E, func(B) BBS], E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() ET.Either[E, func(B) BBS], E, B, BBS],
|
||||
|
||||
tas,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms an array
|
||||
func TraverseRecord[GB ~func() ET.Either[E, B], GBS ~func() ET.Either[E, BBS], AAS ~map[K]A, BBS ~map[K]B, K comparable, E, A, B any](f func(A) GB) func(AAS) GBS {
|
||||
return RR.Traverse[AAS](
|
||||
Of[GBS, E, BBS],
|
||||
Map[GBS, func() ET.Either[E, func(B) BBS], E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func() ET.Either[E, func(B) BBS], E, B, BBS],
|
||||
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceRecord[GA ~func() ET.Either[E, A], GAS ~func() ET.Either[E, AAS], AAS ~map[K]A, GAAS ~map[K]GA, K comparable, E, A any](tas GAAS) GAS {
|
||||
return MonadTraverseRecord[GA, GAS](tas, F.Identity[GA])
|
||||
}
|
58
ioeither/http/request.go
Normal file
58
ioeither/http/request.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
B "github.com/ibm/fp-go/bytes"
|
||||
ER "github.com/ibm/fp-go/errors"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
IOEF "github.com/ibm/fp-go/ioeither/file"
|
||||
J "github.com/ibm/fp-go/json"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
Do(req *http.Request) IOE.IOEither[error, *http.Response]
|
||||
}
|
||||
|
||||
type client struct {
|
||||
delegate *http.Client
|
||||
}
|
||||
|
||||
func (client client) Do(req *http.Request) IOE.IOEither[error, *http.Response] {
|
||||
return IOE.TryCatch(func() (*http.Response, error) {
|
||||
return client.delegate.Do(req)
|
||||
}, ER.IdentityError)
|
||||
}
|
||||
|
||||
func MakeClient(httpClient *http.Client) Client {
|
||||
return client{delegate: httpClient}
|
||||
}
|
||||
|
||||
func ReadAll(client Client) func(*http.Request) IOE.IOEither[error, []byte] {
|
||||
return func(req *http.Request) IOE.IOEither[error, []byte] {
|
||||
return IOEF.ReadAll(F.Pipe2(
|
||||
req,
|
||||
client.Do,
|
||||
IOE.Map[error](func(resp *http.Response) io.ReadCloser {
|
||||
return resp.Body
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func ReadText(client Client) func(*http.Request) IOE.IOEither[error, string] {
|
||||
return F.Flow2(
|
||||
ReadAll(client),
|
||||
IOE.Map[error](B.ToString),
|
||||
)
|
||||
}
|
||||
|
||||
func ReadJson[A any](client Client) func(*http.Request) IOE.IOEither[error, A] {
|
||||
return F.Flow2(
|
||||
ReadAll(client),
|
||||
IOE.ChainEitherK(J.Unmarshal[A]),
|
||||
)
|
||||
}
|
58
ioeither/http/retry_test.go
Normal file
58
ioeither/http/retry_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
AR "github.com/ibm/fp-go/array"
|
||||
E "github.com/ibm/fp-go/either"
|
||||
HE "github.com/ibm/fp-go/either/http"
|
||||
"github.com/ibm/fp-go/errors"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var expLogBackoff = R.ExponentialBackoff(250 * time.Millisecond)
|
||||
|
||||
// our retry policy with a 1s cap
|
||||
var testLogPolicy = R.CapDelay(
|
||||
2*time.Second,
|
||||
R.Monoid.Concat(expLogBackoff, R.LimitRetries(20)),
|
||||
)
|
||||
|
||||
type PostItem struct {
|
||||
UserId uint `json:"userId"`
|
||||
Id uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
func TestRetryHttp(t *testing.T) {
|
||||
// URLs to try, the first URLs have an invalid hostname
|
||||
urls := AR.From("https://jsonplaceholder1.typicode.com/posts/1", "https://jsonplaceholder2.typicode.com/posts/1", "https://jsonplaceholder3.typicode.com/posts/1", "https://jsonplaceholder4.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/1")
|
||||
client := MakeClient(&http.Client{})
|
||||
|
||||
action := func(status R.RetryStatus) IOE.IOEither[error, *PostItem] {
|
||||
return F.Pipe2(
|
||||
HE.GetRequest(urls[status.IterNumber]),
|
||||
IOE.FromEither[error, *http.Request],
|
||||
IOE.Chain(ReadJson[*PostItem](client)),
|
||||
)
|
||||
}
|
||||
|
||||
check := E.Fold(
|
||||
F.Flow2(
|
||||
errors.As[*net.DNSError](),
|
||||
O.Fold(F.Constant(false), F.Constant1[*net.DNSError](true)),
|
||||
),
|
||||
F.Constant1[*PostItem](false),
|
||||
)
|
||||
|
||||
item := IOE.Retrying(testLogPolicy, action, check)()
|
||||
assert.True(t, E.IsRight(item))
|
||||
}
|
217
ioeither/ioeither.go
Normal file
217
ioeither/ioeither.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
I "github.com/ibm/fp-go/io"
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
)
|
||||
|
||||
// IO represents a synchronous computation that may fail
|
||||
// refer to [https://andywhite.xyz/posts/2021-01-27-rte-foundations/#ioeitherlte-agt] for more details
|
||||
type IOEither[E, A any] I.IO[ET.Either[E, A]]
|
||||
|
||||
func MakeIO[E, A any](f IOEither[E, A]) IOEither[E, A] {
|
||||
return G.MakeIO(f)
|
||||
}
|
||||
|
||||
func Left[A, E any](l E) IOEither[E, A] {
|
||||
return G.Left[IOEither[E, A]](l)
|
||||
}
|
||||
|
||||
func Right[E, A any](r A) IOEither[E, A] {
|
||||
return G.Right[IOEither[E, A]](r)
|
||||
}
|
||||
|
||||
func Of[E, A any](r A) IOEither[E, A] {
|
||||
return G.Of[IOEither[E, A]](r)
|
||||
}
|
||||
|
||||
func MonadOf[E, A any](r A) IOEither[E, A] {
|
||||
return G.MonadOf[IOEither[E, A]](r)
|
||||
}
|
||||
|
||||
func LeftIO[A, E any](ml I.IO[E]) IOEither[E, A] {
|
||||
return G.LeftIO[IOEither[E, A]](ml)
|
||||
}
|
||||
|
||||
func RightIO[E, A any](mr I.IO[A]) IOEither[E, A] {
|
||||
return G.RightIO[IOEither[E, A]](mr)
|
||||
}
|
||||
|
||||
func FromEither[E, A any](e ET.Either[E, A]) IOEither[E, A] {
|
||||
return G.FromEither[IOEither[E, A]](e)
|
||||
}
|
||||
|
||||
func FromOption[A, E any](onNone func() E) func(o O.Option[A]) IOEither[E, A] {
|
||||
return G.FromOption[IOEither[E, A]](onNone)
|
||||
}
|
||||
|
||||
func ChainOptionK[A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ChainOptionK[IOEither[E, A], IOEither[E, B]](onNone)
|
||||
}
|
||||
|
||||
func MonadChainIOK[E, A, B any](ma IOEither[E, A], f func(A) I.IO[B]) IOEither[E, B] {
|
||||
return G.MonadChainIOK[IOEither[E, A], IOEither[E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainIOK[E, A, B any](f func(A) I.IO[B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ChainIOK[IOEither[E, A], IOEither[E, B]](f)
|
||||
}
|
||||
|
||||
func FromIO[E, A any](mr I.IO[A]) IOEither[E, A] {
|
||||
return G.FromIO[IOEither[E, A]](mr)
|
||||
}
|
||||
|
||||
func MonadMap[E, A, B any](fa IOEither[E, A], f func(A) B) IOEither[E, B] {
|
||||
return G.MonadMap[IOEither[E, A], IOEither[E, B]](fa, f)
|
||||
}
|
||||
|
||||
func Map[E, A, B any](f func(A) B) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.Map[IOEither[E, A], IOEither[E, B]](f)
|
||||
}
|
||||
|
||||
func MonadMapTo[E, A, B any](fa IOEither[E, A], b B) IOEither[E, B] {
|
||||
return G.MonadMapTo[IOEither[E, A], IOEither[E, B]](fa, b)
|
||||
}
|
||||
|
||||
func MapTo[E, A, B any](b B) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.MapTo[IOEither[E, A], IOEither[E, B]](b)
|
||||
}
|
||||
|
||||
func MonadChain[E, A, B any](fa IOEither[E, A], f func(A) IOEither[E, B]) IOEither[E, B] {
|
||||
return G.MonadChain(fa, f)
|
||||
}
|
||||
|
||||
func Chain[E, A, B any](f func(A) IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.Chain[IOEither[E, A]](f)
|
||||
}
|
||||
|
||||
func MonadChainEitherK[E, A, B any](ma IOEither[E, A], f func(A) ET.Either[E, B]) IOEither[E, B] {
|
||||
return G.MonadChainEitherK[IOEither[E, A], IOEither[E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainEitherK[E, A, B any](f func(A) ET.Either[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ChainEitherK[IOEither[E, A], IOEither[E, B]](f)
|
||||
}
|
||||
|
||||
func MonadAp[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
|
||||
return G.MonadAp[IOEither[E, A], IOEither[E, B]](mab, ma)
|
||||
}
|
||||
|
||||
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||
return G.Ap[IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||
}
|
||||
|
||||
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
|
||||
return G.Flatten(mma)
|
||||
}
|
||||
|
||||
func TryCatch[E, A any](f func() (A, error), onThrow func(error) E) IOEither[E, A] {
|
||||
return G.TryCatch[IOEither[E, A]](f, onThrow)
|
||||
}
|
||||
|
||||
func TryCatchError[A any](f func() (A, error)) IOEither[error, A] {
|
||||
return G.TryCatchError[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Eitherize0[A any](f func() (A, error)) func() IOEither[error, A] {
|
||||
return G.Eitherize0[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Eitherize1[T1, A any](f func(t1 T1) (A, error)) func(T1) IOEither[error, A] {
|
||||
return G.Eitherize1[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Eitherize2[T1, T2, A any](f func(t1 T1, t2 T2) (A, error)) func(T1, T2) IOEither[error, A] {
|
||||
return G.Eitherize2[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Eitherize3[T1, T2, T3, A any](f func(t1 T1, t2 T2, t3 T3) (A, error)) func(T1, T2, T3) IOEither[error, A] {
|
||||
return G.Eitherize3[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Eitherize4[T1, T2, T3, T4, A any](f func(t1 T1, t2 T2, t3 T3, t4 T4) (A, error)) func(T1, T2, T3, T4) IOEither[error, A] {
|
||||
return G.Eitherize4[IOEither[error, A]](f)
|
||||
}
|
||||
|
||||
func Memoize[E, A any](ma IOEither[E, A]) IOEither[E, A] {
|
||||
return G.Memoize(ma)
|
||||
}
|
||||
|
||||
func MonadMapLeft[E1, E2, A any](fa IOEither[E1, A], f func(E1) E2) IOEither[E2, A] {
|
||||
return G.MonadMapLeft[IOEither[E1, A], IOEither[E2, A]](fa, f)
|
||||
}
|
||||
|
||||
func MapLeft[E1, E2, A any](f func(E1) E2) func(IOEither[E1, A]) IOEither[E2, A] {
|
||||
return G.MapLeft[IOEither[E1, A], IOEither[E2, A]](f)
|
||||
}
|
||||
|
||||
func MonadBiMap[E1, E2, A, B any](fa IOEither[E1, A], f func(E1) E2, g func(A) B) IOEither[E2, B] {
|
||||
return G.MonadBiMap[IOEither[E1, A], IOEither[E2, B]](fa, f, g)
|
||||
}
|
||||
|
||||
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
||||
func BiMap[E1, E2, A, B any](f func(E1) E2, g func(A) B) func(IOEither[E1, A]) IOEither[E2, B] {
|
||||
return G.BiMap[IOEither[E1, A], IOEither[E2, B]](f, g)
|
||||
}
|
||||
|
||||
// Fold converts an IOEither into an IO
|
||||
func Fold[E, A, B any](onLeft func(E) I.IO[B], onRight func(A) I.IO[B]) func(IOEither[E, A]) I.IO[B] {
|
||||
return G.Fold[IOEither[E, A]](onLeft, onRight)
|
||||
}
|
||||
|
||||
// GetOrElse extracts the value or maps the error
|
||||
func GetOrElse[E, A any](onLeft func(E) I.IO[A]) func(IOEither[E, A]) I.IO[A] {
|
||||
return G.GetOrElse[IOEither[E, A]](onLeft)
|
||||
}
|
||||
|
||||
// MonadChainTo composes to the second monad ignoring the return value of the first
|
||||
func MonadChainTo[E, A, B any](fa IOEither[E, A], fb IOEither[E, B]) IOEither[E, B] {
|
||||
return G.MonadChainTo(fa, fb)
|
||||
}
|
||||
|
||||
// ChainTo composes to the second monad ignoring the return value of the first
|
||||
func ChainTo[E, A, B any](fb IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
|
||||
return G.ChainTo[IOEither[E, A]](fb)
|
||||
}
|
||||
|
||||
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirst[E, A, B any](ma IOEither[E, A], f func(A) IOEither[E, B]) IOEither[E, A] {
|
||||
return G.MonadChainFirst(ma, f)
|
||||
}
|
||||
|
||||
// ChainFirst runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirst[E, A, B any](f func(A) IOEither[E, B]) func(IOEither[E, A]) IOEither[E, A] {
|
||||
return G.ChainFirst[IOEither[E, A]](f)
|
||||
}
|
||||
|
||||
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
||||
func MonadChainFirstIOK[E, A, B any](ma IOEither[E, A], f func(A) I.IO[B]) IOEither[E, A] {
|
||||
return G.MonadChainFirstIOK(ma, f)
|
||||
}
|
||||
|
||||
// ChainFirsIOKt runs the monad returned by the function but returns the result of the original monad
|
||||
func ChainFirstIOK[E, A, B any](f func(A) I.IO[B]) func(IOEither[E, A]) IOEither[E, A] {
|
||||
return G.ChainFirstIOK[IOEither[E, A]](f)
|
||||
}
|
||||
|
||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||
func WithResource[E, R, A, ANY any](onCreate IOEither[E, R], onRelease func(R) IOEither[E, ANY]) func(func(R) IOEither[E, A]) IOEither[E, A] {
|
||||
return G.WithResource[IOEither[E, A]](onCreate, onRelease)
|
||||
}
|
||||
|
||||
// Swap changes the order of type parameters
|
||||
func Swap[E, A any](val IOEither[E, A]) IOEither[A, E] {
|
||||
return G.Swap[IOEither[E, A], IOEither[A, E]](val)
|
||||
}
|
||||
|
||||
// FromImpure converts a side effect without a return value into a side effect that returns any
|
||||
func FromImpure[E any](f func()) IOEither[E, any] {
|
||||
return G.FromImpure[IOEither[E, any]](f)
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[E, A any](gen func() IOEither[E, A]) IOEither[E, A] {
|
||||
return G.Defer[IOEither[E, A]](gen)
|
||||
}
|
121
ioeither/ioeither_test.go
Normal file
121
ioeither/ioeither_test.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/ibm/fp-go/internal/utils"
|
||||
I "github.com/ibm/fp-go/io"
|
||||
IG "github.com/ibm/fp-go/io/generic"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
assert.Equal(t, E.Of[error](2), F.Pipe1(
|
||||
Of[error](1),
|
||||
Map[error](utils.Double),
|
||||
)())
|
||||
|
||||
}
|
||||
|
||||
func TestChainEitherK(t *testing.T) {
|
||||
f := ChainEitherK(func(n int) E.Either[string, int] {
|
||||
if n > 0 {
|
||||
return E.Of[string](n)
|
||||
}
|
||||
return E.Left[int]("a")
|
||||
|
||||
})
|
||||
assert.Equal(t, E.Right[string](1), f(Right[string](1))())
|
||||
assert.Equal(t, E.Left[int]("a"), f(Right[string](-1))())
|
||||
assert.Equal(t, E.Left[int]("b"), f(Left[int]("b"))())
|
||||
}
|
||||
|
||||
func TestChainOptionK(t *testing.T) {
|
||||
f := ChainOptionK[int, int](F.Constant("a"))(func(n int) O.Option[int] {
|
||||
if n > 0 {
|
||||
return O.Some(n)
|
||||
}
|
||||
return O.None[int]()
|
||||
})
|
||||
|
||||
assert.Equal(t, E.Right[string](1), f(Right[string](1))())
|
||||
assert.Equal(t, E.Left[int]("a"), f(Right[string](-1))())
|
||||
assert.Equal(t, E.Left[int]("b"), f(Left[int]("b"))())
|
||||
}
|
||||
|
||||
func TestFromOption(t *testing.T) {
|
||||
f := FromOption[int](F.Constant("a"))
|
||||
assert.Equal(t, E.Right[string](1), f(O.Some(1))())
|
||||
assert.Equal(t, E.Left[int]("a"), f(O.None[int]())())
|
||||
}
|
||||
|
||||
func TestChainIOK(t *testing.T) {
|
||||
f := ChainIOK[string](func(n int) I.IO[string] {
|
||||
return I.MakeIO(func() string {
|
||||
return fmt.Sprintf("%d", n)
|
||||
})
|
||||
})
|
||||
|
||||
assert.Equal(t, E.Right[string]("1"), f(Right[string](1))())
|
||||
assert.Equal(t, E.Left[string, string]("b"), f(Left[int]("b"))())
|
||||
}
|
||||
|
||||
func TestChainWithIO(t *testing.T) {
|
||||
|
||||
r := F.Pipe1(
|
||||
Of[error]("test"),
|
||||
// sad, we need the generics version ...
|
||||
IG.Map[IOEither[error, string], I.IO[bool]](E.IsRight[error, string]),
|
||||
)
|
||||
|
||||
assert.True(t, r())
|
||||
}
|
||||
|
||||
func TestChainFirst(t *testing.T) {
|
||||
f := func(a string) IOEither[string, int] {
|
||||
if len(a) > 2 {
|
||||
return Of[string](len(a))
|
||||
}
|
||||
return Left[int]("foo")
|
||||
}
|
||||
good := Of[string]("foo")
|
||||
bad := Of[string]("a")
|
||||
ch := ChainFirst(f)
|
||||
|
||||
assert.Equal(t, E.Of[string]("foo"), F.Pipe1(good, ch)())
|
||||
assert.Equal(t, E.Left[string, string]("foo"), F.Pipe1(bad, ch)())
|
||||
}
|
||||
|
||||
func TestChainFirstIOK(t *testing.T) {
|
||||
f := func(a string) I.IO[int] {
|
||||
return I.Of(len(a))
|
||||
}
|
||||
good := Of[string]("foo")
|
||||
ch := ChainFirstIOK[string](f)
|
||||
|
||||
assert.Equal(t, E.Of[string]("foo"), F.Pipe1(good, ch)())
|
||||
}
|
||||
|
||||
func TestApFirst(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of[error]("a"),
|
||||
ApFirst[error, string](Of[error]("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Of[error]("a"), x())
|
||||
}
|
||||
|
||||
func TestApSecond(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of[error]("a"),
|
||||
ApSecond[error, string](Of[error]("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Of[error]("b"), x())
|
||||
}
|
20
ioeither/retry.go
Normal file
20
ioeither/retry.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
)
|
||||
|
||||
// Retrying will retry the actions according to the check policy
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
func Retrying[E, A any](
|
||||
policy R.RetryPolicy,
|
||||
action func(R.RetryStatus) IOEither[E, A],
|
||||
check func(ET.Either[E, A]) bool,
|
||||
) IOEither[E, A] {
|
||||
return G.Retrying(policy, action, check)
|
||||
}
|
33
ioeither/retry_test.go
Normal file
33
ioeither/retry_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var expLogBackoff = R.ExponentialBackoff(10 * time.Millisecond)
|
||||
|
||||
// our retry policy with a 1s cap
|
||||
var testLogPolicy = R.CapDelay(
|
||||
2*time.Second,
|
||||
R.Monoid.Concat(expLogBackoff, R.LimitRetries(20)),
|
||||
)
|
||||
|
||||
func TestRetry(t *testing.T) {
|
||||
action := func(status R.RetryStatus) IOEither[error, string] {
|
||||
if status.IterNumber < 5 {
|
||||
return Left[string](fmt.Errorf("retrying %d", status.IterNumber))
|
||||
}
|
||||
return Of[error](fmt.Sprintf("Retrying %d", status.IterNumber))
|
||||
}
|
||||
check := E.IsLeft[error, string]
|
||||
|
||||
r := Retrying(testLogPolicy, action, check)
|
||||
|
||||
assert.Equal(t, E.Of[error]("Retrying 5"), r())
|
||||
}
|
54
ioeither/sequence.go
Normal file
54
ioeither/sequence.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[E, A any](a IOEither[E, A]) IOEither[E, T.Tuple1[A]] {
|
||||
return G.SequenceT1[
|
||||
IOEither[E, A],
|
||||
IOEither[E, T.Tuple1[A]],
|
||||
](a)
|
||||
}
|
||||
|
||||
func SequenceT2[E, A, B any](
|
||||
a IOEither[E, A],
|
||||
b IOEither[E, B],
|
||||
) IOEither[E, T.Tuple2[A, B]] {
|
||||
return G.SequenceT2[
|
||||
IOEither[E, A],
|
||||
IOEither[E, B],
|
||||
IOEither[E, T.Tuple2[A, B]],
|
||||
](a, b)
|
||||
}
|
||||
|
||||
func SequenceT3[E, A, B, C any](
|
||||
a IOEither[E, A],
|
||||
b IOEither[E, B],
|
||||
c IOEither[E, C],
|
||||
) IOEither[E, T.Tuple3[A, B, C]] {
|
||||
return G.SequenceT3[
|
||||
IOEither[E, A],
|
||||
IOEither[E, B],
|
||||
IOEither[E, C],
|
||||
IOEither[E, T.Tuple3[A, B, C]],
|
||||
](a, b, c)
|
||||
}
|
||||
|
||||
func SequenceT4[E, A, B, C, D any](
|
||||
a IOEither[E, A],
|
||||
b IOEither[E, B],
|
||||
c IOEither[E, C],
|
||||
d IOEither[E, D],
|
||||
) IOEither[E, T.Tuple4[A, B, C, D]] {
|
||||
return G.SequenceT4[
|
||||
IOEither[E, A],
|
||||
IOEither[E, B],
|
||||
IOEither[E, C],
|
||||
IOEither[E, D],
|
||||
IOEither[E, T.Tuple4[A, B, C, D]],
|
||||
](a, b, c, d)
|
||||
}
|
61
ioeither/testing/laws.go
Normal file
61
ioeither/testing/laws.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
L "github.com/ibm/fp-go/internal/monad/testing"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
)
|
||||
|
||||
// AssertLaws asserts the apply monad laws for the `IOEither` monad
|
||||
func AssertLaws[E, A, B, C any](t *testing.T,
|
||||
eqe EQ.Eq[E],
|
||||
eqa EQ.Eq[A],
|
||||
eqb EQ.Eq[B],
|
||||
eqc EQ.Eq[C],
|
||||
|
||||
ab func(A) B,
|
||||
bc func(B) C,
|
||||
) func(a A) bool {
|
||||
|
||||
return L.AssertLaws(t,
|
||||
IOE.Eq(ET.Eq(eqe, eqa)),
|
||||
IOE.Eq(ET.Eq(eqe, eqb)),
|
||||
IOE.Eq(ET.Eq(eqe, eqc)),
|
||||
|
||||
IOE.Of[E, A],
|
||||
IOE.Of[E, B],
|
||||
IOE.Of[E, C],
|
||||
|
||||
IOE.Of[E, func(A) A],
|
||||
IOE.Of[E, func(A) B],
|
||||
IOE.Of[E, func(B) C],
|
||||
IOE.Of[E, func(func(A) B) B],
|
||||
|
||||
IOE.MonadMap[E, A, A],
|
||||
IOE.MonadMap[E, A, B],
|
||||
IOE.MonadMap[E, A, C],
|
||||
IOE.MonadMap[E, B, C],
|
||||
|
||||
IOE.MonadMap[E, func(B) C, func(func(A) B) func(A) C],
|
||||
|
||||
IOE.MonadChain[E, A, A],
|
||||
IOE.MonadChain[E, A, B],
|
||||
IOE.MonadChain[E, A, C],
|
||||
IOE.MonadChain[E, B, C],
|
||||
|
||||
IOE.MonadAp[A, E, A],
|
||||
IOE.MonadAp[B, E, A],
|
||||
IOE.MonadAp[C, E, B],
|
||||
IOE.MonadAp[C, E, A],
|
||||
|
||||
IOE.MonadAp[B, E, func(A) B],
|
||||
IOE.MonadAp[func(A) C, E, func(A) B],
|
||||
|
||||
ab,
|
||||
bc,
|
||||
)
|
||||
|
||||
}
|
33
ioeither/testing/laws_test.go
Normal file
33
ioeither/testing/laws_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMonadLaws(t *testing.T) {
|
||||
// some comparison
|
||||
eqe := EQ.FromStrictEquals[string]()
|
||||
eqa := EQ.FromStrictEquals[bool]()
|
||||
eqb := EQ.FromStrictEquals[int]()
|
||||
eqc := EQ.FromStrictEquals[string]()
|
||||
|
||||
ab := func(a bool) int {
|
||||
if a {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
bc := func(b int) string {
|
||||
return fmt.Sprintf("value %d", b)
|
||||
}
|
||||
|
||||
laws := AssertLaws(t, eqe, eqa, eqb, eqc, ab, bc)
|
||||
|
||||
assert.True(t, laws(true))
|
||||
assert.True(t, laws(false))
|
||||
}
|
25
ioeither/traverse.go
Normal file
25
ioeither/traverse.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
// TraverseArray transforms an array
|
||||
func TraverseArray[E, A, B any](f func(A) IOEither[E, B]) func([]A) IOEither[E, []B] {
|
||||
return G.TraverseArray[IOEither[E, B], IOEither[E, []B], []A](f)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceArray[E, A any](ma []IOEither[E, A]) IOEither[E, []A] {
|
||||
return G.SequenceArray[IOEither[E, A], IOEither[E, []A]](ma)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms a record
|
||||
func TraverseRecord[K comparable, E, A, B any](f func(A) IOEither[E, B]) func(map[K]A) IOEither[E, map[K]B] {
|
||||
return G.TraverseRecord[IOEither[E, B], IOEither[E, map[K]B], map[K]A](f)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceRecord[K comparable, E, A any](ma map[K]IOEither[E, A]) IOEither[E, map[K]A] {
|
||||
return G.SequenceRecord[IOEither[E, A], IOEither[E, map[K]A]](ma)
|
||||
}
|
23
json/json.go
Normal file
23
json/json.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
)
|
||||
|
||||
// Unmarshal parses a JSON data structure from bytes
|
||||
func Unmarshal[A any](data []byte) E.Either[error, A] {
|
||||
return E.TryCatchError(func() (A, error) {
|
||||
var result A
|
||||
err := json.Unmarshal(data, &result)
|
||||
return result, err
|
||||
})
|
||||
}
|
||||
|
||||
// Marshal converts a data structure to json
|
||||
func Marshal[A any](a A) E.Either[error, []byte] {
|
||||
return E.TryCatchError(func() ([]byte, error) {
|
||||
return json.Marshal(a)
|
||||
})
|
||||
}
|
27
json/json_test.go
Normal file
27
json/json_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Json map[string]any
|
||||
|
||||
func TestJsonMarshal(t *testing.T) {
|
||||
|
||||
resRight := Unmarshal[Json]([]byte("{\"a\": \"b\"}"))
|
||||
assert.True(t, E.IsRight(resRight))
|
||||
|
||||
resLeft := Unmarshal[Json]([]byte("{\"a\""))
|
||||
assert.True(t, E.IsLeft(resLeft))
|
||||
|
||||
res1 := F.Pipe1(
|
||||
resRight,
|
||||
E.Chain(Marshal[Json]),
|
||||
)
|
||||
fmt.Println(res1)
|
||||
}
|
22
json/type.go
Normal file
22
json/type.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
E "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
)
|
||||
|
||||
func ToTypeE[A any](src any) E.Either[error, A] {
|
||||
return F.Pipe2(
|
||||
src,
|
||||
Marshal[any],
|
||||
E.Chain(Unmarshal[A]),
|
||||
)
|
||||
}
|
||||
|
||||
func ToTypeO[A any](src any) O.Option[A] {
|
||||
return F.Pipe1(
|
||||
ToTypeE[A](src),
|
||||
E.ToOption[error, A](),
|
||||
)
|
||||
}
|
25
json/type_test.go
Normal file
25
json/type_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type TestType struct {
|
||||
A string `json:"a"`
|
||||
B int `json:"b"`
|
||||
}
|
||||
|
||||
func TestToType(t *testing.T) {
|
||||
|
||||
generic := map[string]any{"a": "value", "b": 1}
|
||||
|
||||
assert.True(t, E.IsRight(ToTypeE[TestType](generic)))
|
||||
assert.True(t, E.IsRight(ToTypeE[TestType](&generic)))
|
||||
|
||||
assert.Equal(t, E.Right[error](&TestType{A: "value", B: 1}), ToTypeE[*TestType](&generic))
|
||||
assert.Equal(t, E.Right[error](TestType{A: "value", B: 1}), F.Pipe1(ToTypeE[*TestType](&generic), E.Map[error](F.Deref[TestType])))
|
||||
}
|
@@ -9,8 +9,8 @@ import (
|
||||
func TraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f func(A) Option[B]) func(GA) Option[GB] {
|
||||
return RA.Traverse[GA](
|
||||
Of[GB],
|
||||
MonadMap[GB, func(B) GB],
|
||||
MonadAp[GB, B],
|
||||
Map[GB, func(B) GB],
|
||||
Ap[GB, B],
|
||||
|
||||
f,
|
||||
)
|
||||
|
@@ -13,176 +13,176 @@ func optionize[R any](f func() (R, bool)) Option[R] {
|
||||
|
||||
// Optionize0 converts a function with 0 parameters returning a tuple of a return value R and a boolean into a function with 0 parameters returning an Option[R]
|
||||
func Optionize0[F ~func() (R, bool), R any](f F) func() Option[R] {
|
||||
return func() Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f()
|
||||
})
|
||||
}
|
||||
return func() Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize0 converts a function with 0 parameters returning a tuple of a return value R and a boolean into a function with 0 parameters returning an Option[R]
|
||||
func Unoptionize0[F ~func() Option[R], R any](f F) func() (R, bool) {
|
||||
return func() (R, bool) {
|
||||
return Unwrap(f())
|
||||
}
|
||||
return func() (R, bool) {
|
||||
return Unwrap(f())
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize1 converts a function with 1 parameters returning a tuple of a return value R and a boolean into a function with 1 parameters returning an Option[R]
|
||||
func Optionize1[F ~func(T0) (R, bool), T0, R any](f F) func(T0) Option[R] {
|
||||
return func(t0 T0) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0)
|
||||
})
|
||||
}
|
||||
return func(t0 T0) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize1 converts a function with 1 parameters returning a tuple of a return value R and a boolean into a function with 1 parameters returning an Option[R]
|
||||
func Unoptionize1[F ~func(T0) Option[R], T0, R any](f F) func(T0) (R, bool) {
|
||||
return func(t0 T0) (R, bool) {
|
||||
return Unwrap(f(t0))
|
||||
}
|
||||
return func(t0 T0) (R, bool) {
|
||||
return Unwrap(f(t0))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize2 converts a function with 2 parameters returning a tuple of a return value R and a boolean into a function with 2 parameters returning an Option[R]
|
||||
func Optionize2[F ~func(T0, T1) (R, bool), T0, T1, R any](f F) func(T0, T1) Option[R] {
|
||||
return func(t0 T0, t1 T1) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize2 converts a function with 2 parameters returning a tuple of a return value R and a boolean into a function with 2 parameters returning an Option[R]
|
||||
func Unoptionize2[F ~func(T0, T1) Option[R], T0, T1, R any](f F) func(T0, T1) (R, bool) {
|
||||
return func(t0 T0, t1 T1) (R, bool) {
|
||||
return Unwrap(f(t0, t1))
|
||||
}
|
||||
return func(t0 T0, t1 T1) (R, bool) {
|
||||
return Unwrap(f(t0, t1))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize3 converts a function with 3 parameters returning a tuple of a return value R and a boolean into a function with 3 parameters returning an Option[R]
|
||||
func Optionize3[F ~func(T0, T1, T2) (R, bool), T0, T1, T2, R any](f F) func(T0, T1, T2) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize3 converts a function with 3 parameters returning a tuple of a return value R and a boolean into a function with 3 parameters returning an Option[R]
|
||||
func Unoptionize3[F ~func(T0, T1, T2) Option[R], T0, T1, T2, R any](f F) func(T0, T1, T2) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize4 converts a function with 4 parameters returning a tuple of a return value R and a boolean into a function with 4 parameters returning an Option[R]
|
||||
func Optionize4[F ~func(T0, T1, T2, T3) (R, bool), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize4 converts a function with 4 parameters returning a tuple of a return value R and a boolean into a function with 4 parameters returning an Option[R]
|
||||
func Unoptionize4[F ~func(T0, T1, T2, T3) Option[R], T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize5 converts a function with 5 parameters returning a tuple of a return value R and a boolean into a function with 5 parameters returning an Option[R]
|
||||
func Optionize5[F ~func(T0, T1, T2, T3, T4) (R, bool), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize5 converts a function with 5 parameters returning a tuple of a return value R and a boolean into a function with 5 parameters returning an Option[R]
|
||||
func Unoptionize5[F ~func(T0, T1, T2, T3, T4) Option[R], T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize6 converts a function with 6 parameters returning a tuple of a return value R and a boolean into a function with 6 parameters returning an Option[R]
|
||||
func Optionize6[F ~func(T0, T1, T2, T3, T4, T5) (R, bool), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize6 converts a function with 6 parameters returning a tuple of a return value R and a boolean into a function with 6 parameters returning an Option[R]
|
||||
func Unoptionize6[F ~func(T0, T1, T2, T3, T4, T5) Option[R], T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize7 converts a function with 7 parameters returning a tuple of a return value R and a boolean into a function with 7 parameters returning an Option[R]
|
||||
func Optionize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, bool), T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize7 converts a function with 7 parameters returning a tuple of a return value R and a boolean into a function with 7 parameters returning an Option[R]
|
||||
func Unoptionize7[F ~func(T0, T1, T2, T3, T4, T5, T6) Option[R], T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize8 converts a function with 8 parameters returning a tuple of a return value R and a boolean into a function with 8 parameters returning an Option[R]
|
||||
func Optionize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, bool), T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize8 converts a function with 8 parameters returning a tuple of a return value R and a boolean into a function with 8 parameters returning an Option[R]
|
||||
func Unoptionize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) Option[R], T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize9 converts a function with 9 parameters returning a tuple of a return value R and a boolean into a function with 9 parameters returning an Option[R]
|
||||
func Optionize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, bool), T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize9 converts a function with 9 parameters returning a tuple of a return value R and a boolean into a function with 9 parameters returning an Option[R]
|
||||
func Unoptionize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Option[R], T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
}
|
||||
|
||||
// Optionize10 converts a function with 10 parameters returning a tuple of a return value R and a boolean into a function with 10 parameters returning an Option[R]
|
||||
func Optionize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, bool), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Option[R] {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
})
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Option[R] {
|
||||
return optionize(func() (R, bool) {
|
||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Unoptionize10 converts a function with 10 parameters returning a tuple of a return value R and a boolean into a function with 10 parameters returning an Option[R]
|
||||
func Unoptionize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Option[R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, bool) {
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, bool) {
|
||||
return Unwrap(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
}
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f func(A) Option[B]) func(GA) Option[GB] {
|
||||
return RR.Traverse[GA](
|
||||
Of[GB],
|
||||
MonadMap[GB, func(B) GB],
|
||||
MonadAp[GB, B],
|
||||
Map[GB, func(B) GB],
|
||||
Ap[GB, B],
|
||||
|
||||
f,
|
||||
)
|
||||
|
87
retry/generic/retry.go
Normal file
87
retry/generic/retry.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
F "github.com/ibm/fp-go/function"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
R "github.com/ibm/fp-go/retry"
|
||||
)
|
||||
|
||||
// Apply policy and delay by its amount if it results in a R.
|
||||
// Returns updated status.
|
||||
// HKTSTATUS = HKT<R.RetryStatus>
|
||||
func applyAndDelay[HKTSTATUS any](
|
||||
monadOf func(R.RetryStatus) HKTSTATUS,
|
||||
monadDelay func(time.Duration) func(HKTSTATUS) HKTSTATUS,
|
||||
) func(policy R.RetryPolicy, status R.RetryStatus) HKTSTATUS {
|
||||
return func(policy R.RetryPolicy, status R.RetryStatus) HKTSTATUS {
|
||||
newStatus := R.ApplyPolicy(policy, status)
|
||||
return F.Pipe1(
|
||||
newStatus.PreviousDelay,
|
||||
O.Fold(
|
||||
F.Nullary2(F.Constant(newStatus), monadOf),
|
||||
func(delay time.Duration) HKTSTATUS {
|
||||
return monadDelay(delay)(monadOf(newStatus))
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Retry combinator for actions that don't raise exceptions, but
|
||||
// signal in their type the outcome has failed. Examples are the
|
||||
// `Option`, `Either` and `EitherT` monads.
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
func Retrying[HKTA, HKTSTATUS, A any](
|
||||
monadChain func(func(A) HKTA) func(HKTA) HKTA,
|
||||
monadChainStatus func(func(R.RetryStatus) HKTA) func(HKTSTATUS) HKTA,
|
||||
monadOf func(A) HKTA,
|
||||
monadOfStatus func(R.RetryStatus) HKTSTATUS,
|
||||
monadDelay func(time.Duration) func(HKTSTATUS) HKTSTATUS,
|
||||
|
||||
policy R.RetryPolicy,
|
||||
action func(R.RetryStatus) HKTA,
|
||||
check func(A) bool,
|
||||
) HKTA {
|
||||
// delay callback
|
||||
applyDelay := applyAndDelay(monadOfStatus, monadDelay)
|
||||
|
||||
// function to check if we need to retry or not
|
||||
checkForRetry := O.FromPredicate(check)
|
||||
|
||||
var f func(status R.RetryStatus) HKTA
|
||||
|
||||
// need some lazy init because we reference it in the chain
|
||||
f = func(status R.RetryStatus) HKTA {
|
||||
return F.Pipe2(
|
||||
status,
|
||||
action,
|
||||
monadChain(func(a A) HKTA {
|
||||
return F.Pipe3(
|
||||
a,
|
||||
checkForRetry,
|
||||
O.Map(func(a A) HKTA {
|
||||
return F.Pipe1(
|
||||
applyDelay(policy, status),
|
||||
monadChainStatus(func(status R.RetryStatus) HKTA {
|
||||
return F.Pipe1(
|
||||
status.PreviousDelay,
|
||||
O.Fold(F.Constant(monadOf(a)), func(_ time.Duration) HKTA {
|
||||
return f(status)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
O.GetOrElse(F.Constant(monadOf(a))),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
// seed
|
||||
return f(R.DefaultRetryStatus)
|
||||
}
|
108
retry/retry.go
Normal file
108
retry/retry.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package Retry
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
F "github.com/ibm/fp-go/function"
|
||||
M "github.com/ibm/fp-go/monoid"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
"github.com/ibm/fp-go/ord"
|
||||
)
|
||||
|
||||
type RetryStatus struct {
|
||||
// Iteration number, where `0` is the first try
|
||||
IterNumber uint
|
||||
// Delay incurred so far from retries
|
||||
CumulativeDelay time.Duration
|
||||
// Latest attempt's delay. Will always be `none` on first run.
|
||||
PreviousDelay O.Option[time.Duration]
|
||||
}
|
||||
|
||||
// RetryPolicy is a function that takes an `RetryStatus` and
|
||||
// possibly returns a delay in milliseconds. Iteration numbers start
|
||||
// at zero and increase by one on each retry. A //None// return value from
|
||||
// the function implies we have reached the retry limit.
|
||||
type RetryPolicy = func(RetryStatus) O.Option[time.Duration]
|
||||
|
||||
const emptyDuration = time.Duration(0)
|
||||
|
||||
var ordDuration = ord.FromStrictCompare[time.Duration]()
|
||||
|
||||
// 'RetryPolicy' is a 'Monoid'. You can collapse multiple strategies into one using 'concat'.
|
||||
// The semantics of this combination are as follows:
|
||||
//
|
||||
// 1. If either policy returns 'None', the combined policy returns
|
||||
// 'None'. This can be used to inhibit after a number of retries,
|
||||
// for example.
|
||||
//
|
||||
// 2. If both policies return a delay, the larger delay will be used.
|
||||
// This is quite natural when combining multiple policies to achieve a
|
||||
// certain effect.
|
||||
var Monoid = M.FunctionMonoid[RetryStatus](O.ApplicativeMonoid(M.MakeMonoid(
|
||||
ord.MaxSemigroup(ordDuration).Concat, emptyDuration)))
|
||||
|
||||
// LimitRetries retries immediately, but only up to `i` times.
|
||||
func LimitRetries(i uint) RetryPolicy {
|
||||
pred := func(value uint) bool {
|
||||
return value < i
|
||||
}
|
||||
empty := F.Constant1[uint](emptyDuration)
|
||||
return func(status RetryStatus) O.Option[time.Duration] {
|
||||
return F.Pipe2(
|
||||
status.IterNumber,
|
||||
O.FromPredicate(pred),
|
||||
O.Map(empty),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ConstantDelay delays with unlimited retries
|
||||
func ConstantDelay(delay time.Duration) RetryPolicy {
|
||||
return F.Constant1[RetryStatus](O.Of(delay))
|
||||
}
|
||||
|
||||
// CapDelay sets a time-upperbound for any delays that may be directed by the
|
||||
// given policy. This function does not terminate the retrying. The policy
|
||||
// capDelay(maxDelay, exponentialBackoff(n))` will never stop retrying. It
|
||||
// will reach a state where it retries forever with a delay of `maxDelay`
|
||||
// between each one. To get termination you need to use one of the
|
||||
// 'limitRetries' function variants.
|
||||
func CapDelay(maxDelay time.Duration, policy RetryPolicy) RetryPolicy {
|
||||
return F.Flow2(
|
||||
policy,
|
||||
O.Map(F.Bind1st(ord.Min(ordDuration), maxDelay)),
|
||||
)
|
||||
}
|
||||
|
||||
// ExponentialBackoff grows delay exponentially each iteration.
|
||||
// Each delay will increase by a factor of two.
|
||||
func ExponentialBackoff(delay time.Duration) RetryPolicy {
|
||||
return func(status RetryStatus) O.Option[time.Duration] {
|
||||
return O.Some(delay * time.Duration(math.Pow(2, float64(status.IterNumber))))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial, default retry status. Exported mostly to allow user code
|
||||
* to test their handlers and retry policies.
|
||||
*/
|
||||
var DefaultRetryStatus = RetryStatus{
|
||||
IterNumber: 0,
|
||||
CumulativeDelay: 0,
|
||||
PreviousDelay: O.None[time.Duration](),
|
||||
}
|
||||
|
||||
var getOrElseDelay = O.GetOrElse(F.Constant(emptyDuration))
|
||||
|
||||
/**
|
||||
* Apply policy on status to see what the decision would be.
|
||||
*/
|
||||
func ApplyPolicy(policy RetryPolicy, status RetryStatus) RetryStatus {
|
||||
previousDelay := policy(status)
|
||||
return RetryStatus{
|
||||
IterNumber: status.IterNumber + 1,
|
||||
CumulativeDelay: status.CumulativeDelay + getOrElseDelay(previousDelay),
|
||||
PreviousDelay: previousDelay,
|
||||
}
|
||||
}
|
631
tuple/gen.go
631
tuple/gen.go
@@ -3,7 +3,6 @@
|
||||
// 2023-07-14 13:19:47.4331101 +0200 CEST m=+0.011802301
|
||||
package tuple
|
||||
|
||||
|
||||
import (
|
||||
M "github.com/ibm/fp-go/monoid"
|
||||
O "github.com/ibm/fp-go/ord"
|
||||
@@ -11,520 +10,630 @@ import (
|
||||
|
||||
// Tuple1 is a struct that carries 1 independently typed values
|
||||
type Tuple1[T1 any] struct {
|
||||
F1 T1
|
||||
F1 T1
|
||||
}
|
||||
|
||||
// Tuple2 is a struct that carries 2 independently typed values
|
||||
type Tuple2[T1, T2 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F1 T1
|
||||
F2 T2
|
||||
}
|
||||
|
||||
// Tuple3 is a struct that carries 3 independently typed values
|
||||
type Tuple3[T1, T2, T3 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
}
|
||||
|
||||
// Tuple4 is a struct that carries 4 independently typed values
|
||||
type Tuple4[T1, T2, T3, T4 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
}
|
||||
|
||||
// Tuple5 is a struct that carries 5 independently typed values
|
||||
type Tuple5[T1, T2, T3, T4, T5 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
}
|
||||
|
||||
// Tuple6 is a struct that carries 6 independently typed values
|
||||
type Tuple6[T1, T2, T3, T4, T5, T6 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
}
|
||||
|
||||
// Tuple7 is a struct that carries 7 independently typed values
|
||||
type Tuple7[T1, T2, T3, T4, T5, T6, T7 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
}
|
||||
|
||||
// Tuple8 is a struct that carries 8 independently typed values
|
||||
type Tuple8[T1, T2, T3, T4, T5, T6, T7, T8 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
}
|
||||
|
||||
// Tuple9 is a struct that carries 9 independently typed values
|
||||
type Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
F9 T9
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
F9 T9
|
||||
}
|
||||
|
||||
// Tuple10 is a struct that carries 10 independently typed values
|
||||
type Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
F9 T9
|
||||
F10 T10
|
||||
F1 T1
|
||||
F2 T2
|
||||
F3 T3
|
||||
F4 T4
|
||||
F5 T5
|
||||
F6 T6
|
||||
F7 T7
|
||||
F8 T8
|
||||
F9 T9
|
||||
F10 T10
|
||||
}
|
||||
|
||||
// MakeTuple1 is a function that converts its 1 parameters into a [Tuple1]
|
||||
func MakeTuple1[T1 any](t1 T1) Tuple1[T1] {
|
||||
return Tuple1[T1]{t1}
|
||||
return Tuple1[T1]{t1}
|
||||
}
|
||||
|
||||
// Tupled1 converts a function with 1 parameters returning into a function taking a Tuple1
|
||||
// The inverse function is [Untupled1]
|
||||
func Tupled1[F ~func(T1) R, T1, R any](f F) func(Tuple1[T1]) R {
|
||||
return func(t Tuple1[T1]) R {
|
||||
return f(t.F1)
|
||||
}
|
||||
return func(t Tuple1[T1]) R {
|
||||
return f(t.F1)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled1 converts a function with a [Tuple1] parameter into a function with 1 parameters
|
||||
// The inverse function is [Tupled1]
|
||||
func Untupled1[F ~func(Tuple1[T1]) R, T1, R any](f F) func(T1) R {
|
||||
return func(t1 T1) R {
|
||||
return f(MakeTuple1(t1))
|
||||
}
|
||||
return func(t1 T1) R {
|
||||
return f(MakeTuple1(t1))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid1 creates a [Monoid] for a [Tuple1] based on 1 monoids for the contained types
|
||||
func Monoid1[T1 any](m1 M.Monoid[T1]) M.Monoid[Tuple1[T1]] {
|
||||
return M.MakeMonoid(func(l, r Tuple1[T1]) Tuple1[T1]{
|
||||
return MakeTuple1(m1.Concat(l.F1, r.F1))
|
||||
}, MakeTuple1(m1.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple1[T1]) Tuple1[T1] {
|
||||
return MakeTuple1(m1.Concat(l.F1, r.F1))
|
||||
}, MakeTuple1(m1.Empty()))
|
||||
}
|
||||
|
||||
// Ord1 creates n [Ord] for a [Tuple1] based on 1 [Ord]s for the contained types
|
||||
func Ord1[T1 any](o1 O.Ord[T1]) O.Ord[Tuple1[T1]] {
|
||||
return O.MakeOrd(func(l, r Tuple1[T1]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple1[T1]) bool {
|
||||
return o1.Equals(l.F1, r.F1)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple1[T1]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple1[T1]) bool {
|
||||
return o1.Equals(l.F1, r.F1)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple2 is a function that converts its 2 parameters into a [Tuple2]
|
||||
func MakeTuple2[T1, T2 any](t1 T1, t2 T2) Tuple2[T1, T2] {
|
||||
return Tuple2[T1, T2]{t1, t2}
|
||||
return Tuple2[T1, T2]{t1, t2}
|
||||
}
|
||||
|
||||
// Tupled2 converts a function with 2 parameters returning into a function taking a Tuple2
|
||||
// The inverse function is [Untupled2]
|
||||
func Tupled2[F ~func(T1, T2) R, T1, T2, R any](f F) func(Tuple2[T1, T2]) R {
|
||||
return func(t Tuple2[T1, T2]) R {
|
||||
return f(t.F1, t.F2)
|
||||
}
|
||||
return func(t Tuple2[T1, T2]) R {
|
||||
return f(t.F1, t.F2)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled2 converts a function with a [Tuple2] parameter into a function with 2 parameters
|
||||
// The inverse function is [Tupled2]
|
||||
func Untupled2[F ~func(Tuple2[T1, T2]) R, T1, T2, R any](f F) func(T1, T2) R {
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f(MakeTuple2(t1, t2))
|
||||
}
|
||||
return func(t1 T1, t2 T2) R {
|
||||
return f(MakeTuple2(t1, t2))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid2 creates a [Monoid] for a [Tuple2] based on 2 monoids for the contained types
|
||||
func Monoid2[T1, T2 any](m1 M.Monoid[T1], m2 M.Monoid[T2]) M.Monoid[Tuple2[T1, T2]] {
|
||||
return M.MakeMonoid(func(l, r Tuple2[T1, T2]) Tuple2[T1, T2]{
|
||||
return MakeTuple2(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2))
|
||||
}, MakeTuple2(m1.Empty(), m2.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple2[T1, T2]) Tuple2[T1, T2] {
|
||||
return MakeTuple2(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2))
|
||||
}, MakeTuple2(m1.Empty(), m2.Empty()))
|
||||
}
|
||||
|
||||
// Ord2 creates n [Ord] for a [Tuple2] based on 2 [Ord]s for the contained types
|
||||
func Ord2[T1, T2 any](o1 O.Ord[T1], o2 O.Ord[T2]) O.Ord[Tuple2[T1, T2]] {
|
||||
return O.MakeOrd(func(l, r Tuple2[T1, T2]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple2[T1, T2]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple2[T1, T2]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple2[T1, T2]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple3 is a function that converts its 3 parameters into a [Tuple3]
|
||||
func MakeTuple3[T1, T2, T3 any](t1 T1, t2 T2, t3 T3) Tuple3[T1, T2, T3] {
|
||||
return Tuple3[T1, T2, T3]{t1, t2, t3}
|
||||
return Tuple3[T1, T2, T3]{t1, t2, t3}
|
||||
}
|
||||
|
||||
// Tupled3 converts a function with 3 parameters returning into a function taking a Tuple3
|
||||
// The inverse function is [Untupled3]
|
||||
func Tupled3[F ~func(T1, T2, T3) R, T1, T2, T3, R any](f F) func(Tuple3[T1, T2, T3]) R {
|
||||
return func(t Tuple3[T1, T2, T3]) R {
|
||||
return f(t.F1, t.F2, t.F3)
|
||||
}
|
||||
return func(t Tuple3[T1, T2, T3]) R {
|
||||
return f(t.F1, t.F2, t.F3)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled3 converts a function with a [Tuple3] parameter into a function with 3 parameters
|
||||
// The inverse function is [Tupled3]
|
||||
func Untupled3[F ~func(Tuple3[T1, T2, T3]) R, T1, T2, T3, R any](f F) func(T1, T2, T3) R {
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
return f(MakeTuple3(t1, t2, t3))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3) R {
|
||||
return f(MakeTuple3(t1, t2, t3))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid3 creates a [Monoid] for a [Tuple3] based on 3 monoids for the contained types
|
||||
func Monoid3[T1, T2, T3 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3]) M.Monoid[Tuple3[T1, T2, T3]] {
|
||||
return M.MakeMonoid(func(l, r Tuple3[T1, T2, T3]) Tuple3[T1, T2, T3]{
|
||||
return MakeTuple3(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3))
|
||||
}, MakeTuple3(m1.Empty(), m2.Empty(), m3.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple3[T1, T2, T3]) Tuple3[T1, T2, T3] {
|
||||
return MakeTuple3(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3))
|
||||
}, MakeTuple3(m1.Empty(), m2.Empty(), m3.Empty()))
|
||||
}
|
||||
|
||||
// Ord3 creates n [Ord] for a [Tuple3] based on 3 [Ord]s for the contained types
|
||||
func Ord3[T1, T2, T3 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3]) O.Ord[Tuple3[T1, T2, T3]] {
|
||||
return O.MakeOrd(func(l, r Tuple3[T1, T2, T3]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple3[T1, T2, T3]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple3[T1, T2, T3]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple3[T1, T2, T3]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple4 is a function that converts its 4 parameters into a [Tuple4]
|
||||
func MakeTuple4[T1, T2, T3, T4 any](t1 T1, t2 T2, t3 T3, t4 T4) Tuple4[T1, T2, T3, T4] {
|
||||
return Tuple4[T1, T2, T3, T4]{t1, t2, t3, t4}
|
||||
return Tuple4[T1, T2, T3, T4]{t1, t2, t3, t4}
|
||||
}
|
||||
|
||||
// Tupled4 converts a function with 4 parameters returning into a function taking a Tuple4
|
||||
// The inverse function is [Untupled4]
|
||||
func Tupled4[F ~func(T1, T2, T3, T4) R, T1, T2, T3, T4, R any](f F) func(Tuple4[T1, T2, T3, T4]) R {
|
||||
return func(t Tuple4[T1, T2, T3, T4]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4)
|
||||
}
|
||||
return func(t Tuple4[T1, T2, T3, T4]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled4 converts a function with a [Tuple4] parameter into a function with 4 parameters
|
||||
// The inverse function is [Tupled4]
|
||||
func Untupled4[F ~func(Tuple4[T1, T2, T3, T4]) R, T1, 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 f(MakeTuple4(t1, t2, t3, t4))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4) R {
|
||||
return f(MakeTuple4(t1, t2, t3, t4))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid4 creates a [Monoid] for a [Tuple4] based on 4 monoids for the contained types
|
||||
func Monoid4[T1, T2, T3, T4 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4]) M.Monoid[Tuple4[T1, T2, T3, T4]] {
|
||||
return M.MakeMonoid(func(l, r Tuple4[T1, T2, T3, T4]) Tuple4[T1, T2, T3, T4]{
|
||||
return MakeTuple4(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4))
|
||||
}, MakeTuple4(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple4[T1, T2, T3, T4]) Tuple4[T1, T2, T3, T4] {
|
||||
return MakeTuple4(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4))
|
||||
}, MakeTuple4(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty()))
|
||||
}
|
||||
|
||||
// Ord4 creates n [Ord] for a [Tuple4] based on 4 [Ord]s for the contained types
|
||||
func Ord4[T1, T2, T3, T4 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4]) O.Ord[Tuple4[T1, T2, T3, T4]] {
|
||||
return O.MakeOrd(func(l, r Tuple4[T1, T2, T3, T4]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple4[T1, T2, T3, T4]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple4[T1, T2, T3, T4]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple4[T1, T2, T3, T4]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple5 is a function that converts its 5 parameters into a [Tuple5]
|
||||
func MakeTuple5[T1, T2, T3, T4, T5 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Tuple5[T1, T2, T3, T4, T5] {
|
||||
return Tuple5[T1, T2, T3, T4, T5]{t1, t2, t3, t4, t5}
|
||||
return Tuple5[T1, T2, T3, T4, T5]{t1, t2, t3, t4, t5}
|
||||
}
|
||||
|
||||
// Tupled5 converts a function with 5 parameters returning into a function taking a Tuple5
|
||||
// The inverse function is [Untupled5]
|
||||
func Tupled5[F ~func(T1, T2, T3, T4, T5) R, T1, T2, T3, T4, T5, R any](f F) func(Tuple5[T1, T2, T3, T4, T5]) R {
|
||||
return func(t Tuple5[T1, T2, T3, T4, T5]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5)
|
||||
}
|
||||
return func(t Tuple5[T1, T2, T3, T4, T5]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled5 converts a function with a [Tuple5] parameter into a function with 5 parameters
|
||||
// The inverse function is [Tupled5]
|
||||
func Untupled5[F ~func(Tuple5[T1, T2, T3, T4, T5]) R, T1, T2, T3, T4, T5, R any](f F) func(T1, T2, T3, T4, T5) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) R {
|
||||
return f(MakeTuple5(t1, t2, t3, t4, t5))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) R {
|
||||
return f(MakeTuple5(t1, t2, t3, t4, t5))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid5 creates a [Monoid] for a [Tuple5] based on 5 monoids for the contained types
|
||||
func Monoid5[T1, T2, T3, T4, T5 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5]) M.Monoid[Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return M.MakeMonoid(func(l, r Tuple5[T1, T2, T3, T4, T5]) Tuple5[T1, T2, T3, T4, T5]{
|
||||
return MakeTuple5(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5))
|
||||
}, MakeTuple5(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple5[T1, T2, T3, T4, T5]) Tuple5[T1, T2, T3, T4, T5] {
|
||||
return MakeTuple5(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5))
|
||||
}, MakeTuple5(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty()))
|
||||
}
|
||||
|
||||
// Ord5 creates n [Ord] for a [Tuple5] based on 5 [Ord]s for the contained types
|
||||
func Ord5[T1, T2, T3, T4, T5 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5]) O.Ord[Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return O.MakeOrd(func(l, r Tuple5[T1, T2, T3, T4, T5]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple5[T1, T2, T3, T4, T5]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple5[T1, T2, T3, T4, T5]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple5[T1, T2, T3, T4, T5]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple6 is a function that converts its 6 parameters into a [Tuple6]
|
||||
func MakeTuple6[T1, T2, T3, T4, T5, T6 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Tuple6[T1, T2, T3, T4, T5, T6] {
|
||||
return Tuple6[T1, T2, T3, T4, T5, T6]{t1, t2, t3, t4, t5, t6}
|
||||
return Tuple6[T1, T2, T3, T4, T5, T6]{t1, t2, t3, t4, t5, t6}
|
||||
}
|
||||
|
||||
// Tupled6 converts a function with 6 parameters returning into a function taking a Tuple6
|
||||
// The inverse function is [Untupled6]
|
||||
func Tupled6[F ~func(T1, T2, T3, T4, T5, T6) R, T1, T2, T3, T4, T5, T6, R any](f F) func(Tuple6[T1, T2, T3, T4, T5, T6]) R {
|
||||
return func(t Tuple6[T1, T2, T3, T4, T5, T6]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6)
|
||||
}
|
||||
return func(t Tuple6[T1, T2, T3, T4, T5, T6]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled6 converts a function with a [Tuple6] parameter into a function with 6 parameters
|
||||
// The inverse function is [Tupled6]
|
||||
func Untupled6[F ~func(Tuple6[T1, T2, T3, T4, T5, T6]) R, T1, T2, T3, T4, T5, T6, R any](f F) func(T1, T2, T3, T4, T5, T6) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) R {
|
||||
return f(MakeTuple6(t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) R {
|
||||
return f(MakeTuple6(t1, t2, t3, t4, t5, t6))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid6 creates a [Monoid] for a [Tuple6] based on 6 monoids for the contained types
|
||||
func Monoid6[T1, T2, T3, T4, T5, T6 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6]) M.Monoid[Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return M.MakeMonoid(func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) Tuple6[T1, T2, T3, T4, T5, T6]{
|
||||
return MakeTuple6(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6))
|
||||
}, MakeTuple6(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) Tuple6[T1, T2, T3, T4, T5, T6] {
|
||||
return MakeTuple6(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6))
|
||||
}, MakeTuple6(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty()))
|
||||
}
|
||||
|
||||
// Ord6 creates n [Ord] for a [Tuple6] based on 6 [Ord]s for the contained types
|
||||
func Ord6[T1, T2, T3, T4, T5, T6 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6]) O.Ord[Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return O.MakeOrd(func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
if c:= o6.Compare(l.F6, r.F6); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o6.Compare(l.F6, r.F6); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple6[T1, T2, T3, T4, T5, T6]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple7 is a function that converts its 7 parameters into a [Tuple7]
|
||||
func MakeTuple7[T1, T2, T3, T4, T5, T6, T7 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Tuple7[T1, T2, T3, T4, T5, T6, T7] {
|
||||
return Tuple7[T1, T2, T3, T4, T5, T6, T7]{t1, t2, t3, t4, t5, t6, t7}
|
||||
return Tuple7[T1, T2, T3, T4, T5, T6, T7]{t1, t2, t3, t4, t5, t6, t7}
|
||||
}
|
||||
|
||||
// Tupled7 converts a function with 7 parameters returning into a function taking a Tuple7
|
||||
// The inverse function is [Untupled7]
|
||||
func Tupled7[F ~func(T1, T2, T3, T4, T5, T6, T7) R, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(Tuple7[T1, T2, T3, T4, T5, T6, T7]) R {
|
||||
return func(t Tuple7[T1, T2, T3, T4, T5, T6, T7]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7)
|
||||
}
|
||||
return func(t Tuple7[T1, T2, T3, T4, T5, T6, T7]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled7 converts a function with a [Tuple7] parameter into a function with 7 parameters
|
||||
// The inverse function is [Tupled7]
|
||||
func Untupled7[F ~func(Tuple7[T1, T2, T3, T4, T5, T6, T7]) R, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T1, T2, T3, T4, T5, T6, T7) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) R {
|
||||
return f(MakeTuple7(t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) R {
|
||||
return f(MakeTuple7(t1, t2, t3, t4, t5, t6, t7))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid7 creates a [Monoid] for a [Tuple7] based on 7 monoids for the contained types
|
||||
func Monoid7[T1, T2, T3, T4, T5, T6, T7 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7]) M.Monoid[Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return M.MakeMonoid(func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) Tuple7[T1, T2, T3, T4, T5, T6, T7]{
|
||||
return MakeTuple7(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7))
|
||||
}, MakeTuple7(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) Tuple7[T1, T2, T3, T4, T5, T6, T7] {
|
||||
return MakeTuple7(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7))
|
||||
}, MakeTuple7(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty()))
|
||||
}
|
||||
|
||||
// Ord7 creates n [Ord] for a [Tuple7] based on 7 [Ord]s for the contained types
|
||||
func Ord7[T1, T2, T3, T4, T5, T6, T7 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7]) O.Ord[Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return O.MakeOrd(func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
if c:= o6.Compare(l.F6, r.F6); c != 0 {return c}
|
||||
if c:= o7.Compare(l.F7, r.F7); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o6.Compare(l.F6, r.F6); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o7.Compare(l.F7, r.F7); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple7[T1, T2, T3, T4, T5, T6, T7]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple8 is a function that converts its 8 parameters into a [Tuple8]
|
||||
func MakeTuple8[T1, T2, T3, T4, T5, T6, T7, T8 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] {
|
||||
return Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]{t1, t2, t3, t4, t5, t6, t7, t8}
|
||||
return Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]{t1, t2, t3, t4, t5, t6, t7, t8}
|
||||
}
|
||||
|
||||
// Tupled8 converts a function with 8 parameters returning into a function taking a Tuple8
|
||||
// The inverse function is [Untupled8]
|
||||
func Tupled8[F ~func(T1, T2, T3, T4, T5, T6, T7, T8) R, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) R {
|
||||
return func(t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8)
|
||||
}
|
||||
return func(t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled8 converts a function with a [Tuple8] parameter into a function with 8 parameters
|
||||
// The inverse function is [Tupled8]
|
||||
func Untupled8[F ~func(Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) R, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) R {
|
||||
return f(MakeTuple8(t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) R {
|
||||
return f(MakeTuple8(t1, t2, t3, t4, t5, t6, t7, t8))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid8 creates a [Monoid] for a [Tuple8] based on 8 monoids for the contained types
|
||||
func Monoid8[T1, T2, T3, T4, T5, T6, T7, T8 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8]) M.Monoid[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return M.MakeMonoid(func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]{
|
||||
return MakeTuple8(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8))
|
||||
}, MakeTuple8(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] {
|
||||
return MakeTuple8(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8))
|
||||
}, MakeTuple8(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty()))
|
||||
}
|
||||
|
||||
// Ord8 creates n [Ord] for a [Tuple8] based on 8 [Ord]s for the contained types
|
||||
func Ord8[T1, T2, T3, T4, T5, T6, T7, T8 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8]) O.Ord[Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return O.MakeOrd(func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
if c:= o6.Compare(l.F6, r.F6); c != 0 {return c}
|
||||
if c:= o7.Compare(l.F7, r.F7); c != 0 {return c}
|
||||
if c:= o8.Compare(l.F8, r.F8); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o6.Compare(l.F6, r.F6); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o7.Compare(l.F7, r.F7); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o8.Compare(l.F8, r.F8); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple9 is a function that converts its 9 parameters into a [Tuple9]
|
||||
func MakeTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] {
|
||||
return Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]{t1, t2, t3, t4, t5, t6, t7, t8, t9}
|
||||
return Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]{t1, t2, t3, t4, t5, t6, t7, t8, t9}
|
||||
}
|
||||
|
||||
// Tupled9 converts a function with 9 parameters returning into a function taking a Tuple9
|
||||
// The inverse function is [Untupled9]
|
||||
func Tupled9[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) R {
|
||||
return func(t Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9)
|
||||
}
|
||||
return func(t Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled9 converts a function with a [Tuple9] parameter into a function with 9 parameters
|
||||
// The inverse function is [Tupled9]
|
||||
func Untupled9[F ~func(Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) R {
|
||||
return f(MakeTuple9(t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) R {
|
||||
return f(MakeTuple9(t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid9 creates a [Monoid] for a [Tuple9] based on 9 monoids for the contained types
|
||||
func Monoid9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9]) M.Monoid[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return M.MakeMonoid(func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]{
|
||||
return MakeTuple9(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9))
|
||||
}, MakeTuple9(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] {
|
||||
return MakeTuple9(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9))
|
||||
}, MakeTuple9(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty()))
|
||||
}
|
||||
|
||||
// Ord9 creates n [Ord] for a [Tuple9] based on 9 [Ord]s for the contained types
|
||||
func Ord9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9]) O.Ord[Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return O.MakeOrd(func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
if c:= o6.Compare(l.F6, r.F6); c != 0 {return c}
|
||||
if c:= o7.Compare(l.F7, r.F7); c != 0 {return c}
|
||||
if c:= o8.Compare(l.F8, r.F8); c != 0 {return c}
|
||||
if c:= o9.Compare(l.F9, r.F9); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o6.Compare(l.F6, r.F6); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o7.Compare(l.F7, r.F7); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o8.Compare(l.F8, r.F8); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o9.Compare(l.F9, r.F9); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9)
|
||||
})
|
||||
}
|
||||
|
||||
// MakeTuple10 is a function that converts its 10 parameters into a [Tuple10]
|
||||
func MakeTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10) Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {
|
||||
return Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10}
|
||||
return Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10}
|
||||
}
|
||||
|
||||
// Tupled10 converts a function with 10 parameters returning into a function taking a Tuple10
|
||||
// The inverse function is [Untupled10]
|
||||
func Tupled10[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) R {
|
||||
return func(t Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10)
|
||||
}
|
||||
return func(t Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) R {
|
||||
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10)
|
||||
}
|
||||
}
|
||||
|
||||
// Untupled10 converts a function with a [Tuple10] parameter into a function with 10 parameters
|
||||
// The inverse function is [Tupled10]
|
||||
func Untupled10[F ~func(Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) R {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10) R {
|
||||
return f(MakeTuple10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))
|
||||
}
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10) R {
|
||||
return f(MakeTuple10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))
|
||||
}
|
||||
}
|
||||
|
||||
// Monoid10 creates a [Monoid] for a [Tuple10] based on 10 monoids for the contained types
|
||||
func Monoid10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10]) M.Monoid[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return M.MakeMonoid(func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]{
|
||||
return MakeTuple10(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10))
|
||||
}, MakeTuple10(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty()))
|
||||
return M.MakeMonoid(func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] {
|
||||
return MakeTuple10(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10))
|
||||
}, MakeTuple10(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty()))
|
||||
}
|
||||
|
||||
// Ord10 creates n [Ord] for a [Tuple10] based on 10 [Ord]s for the contained types
|
||||
func Ord10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10]) O.Ord[Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return O.MakeOrd(func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) int {
|
||||
if c:= o1.Compare(l.F1, r.F1); c != 0 {return c}
|
||||
if c:= o2.Compare(l.F2, r.F2); c != 0 {return c}
|
||||
if c:= o3.Compare(l.F3, r.F3); c != 0 {return c}
|
||||
if c:= o4.Compare(l.F4, r.F4); c != 0 {return c}
|
||||
if c:= o5.Compare(l.F5, r.F5); c != 0 {return c}
|
||||
if c:= o6.Compare(l.F6, r.F6); c != 0 {return c}
|
||||
if c:= o7.Compare(l.F7, r.F7); c != 0 {return c}
|
||||
if c:= o8.Compare(l.F8, r.F8); c != 0 {return c}
|
||||
if c:= o9.Compare(l.F9, r.F9); c != 0 {return c}
|
||||
if c:= o10.Compare(l.F10, r.F10); c != 0 {return c}
|
||||
return 0
|
||||
}, func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10)
|
||||
})
|
||||
return O.MakeOrd(func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) int {
|
||||
if c := o1.Compare(l.F1, r.F1); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o2.Compare(l.F2, r.F2); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o3.Compare(l.F3, r.F3); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o4.Compare(l.F4, r.F4); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o5.Compare(l.F5, r.F5); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o6.Compare(l.F6, r.F6); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o7.Compare(l.F7, r.F7); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o8.Compare(l.F8, r.F8); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o9.Compare(l.F9, r.F9); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := o10.Compare(l.F10, r.F10); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}, func(l, r Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) bool {
|
||||
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10)
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user