mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: add automation for TraverseTuple and SequenceTuple
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
228
cli/apply.go
228
cli/apply.go
@@ -10,10 +10,10 @@ import (
|
||||
C "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func generateSequenceT(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "\n// SequenceT%d is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.\n", i)
|
||||
fmt.Fprintf(f, "// The function takes %d higher higher kinded types and returns a higher kinded type of a [Tuple%d] with the resolved values.\n", i, i)
|
||||
fmt.Fprintf(f, "func SequenceT%d[\n", i)
|
||||
func generateTraverseTuple(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "\n// TraverseTuple%d is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.\n", i)
|
||||
fmt.Fprintf(f, "// The function takes a [Tuple%d] of base types and %d functions that transform these based types into higher higher kinded types. It returns a higher kinded type of a [Tuple%d] with the resolved values.\n", i, i, i)
|
||||
fmt.Fprintf(f, "func TraverseTuple%d[\n", i)
|
||||
// map as the starting point
|
||||
fmt.Fprintf(f, " MAP ~func(")
|
||||
for j := 0; j < i; j++ {
|
||||
@@ -24,7 +24,115 @@ func generateSequenceT(f *os.File, i int) {
|
||||
}
|
||||
fmt.Fprintf(f, " ")
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") func(HKT_T1)")
|
||||
if i > 1 {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := 1; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d", i)
|
||||
}
|
||||
fmt.Fprintf(f, ",\n")
|
||||
// the applicatives
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " AP%d ~func(", j)
|
||||
fmt.Fprintf(f, "HKT_T%d) func(", j+1)
|
||||
fmt.Fprintf(f, "HKT_F")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, ")")
|
||||
if j+1 < i {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := j + 1; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d", i)
|
||||
}
|
||||
fmt.Fprintf(f, ",\n")
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " F%d ~func(A%d) HKT_T%d,\n", j+1, j+1, j+1)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " A%d, T%d,\n", j+1, j+1)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " HKT_T%d, // HKT[T%d]\n", j+1, j+1)
|
||||
}
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, ", // HKT[")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "func(T%d) ", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
}
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d any, // HKT[", i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
fmt.Fprintf(f, "](\n")
|
||||
|
||||
// the callbacks
|
||||
fmt.Fprintf(f, " fmap MAP,\n")
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " fap%d AP%d,\n", j, j)
|
||||
}
|
||||
// the transformer functions
|
||||
for j := 1; j <= i; j++ {
|
||||
fmt.Fprintf(f, " f%d F%d,\n", j, j)
|
||||
}
|
||||
// the parameters
|
||||
fmt.Fprintf(f, " t T.Tuple%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "A%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "],\n")
|
||||
fmt.Fprintf(f, ") HKT_TUPLE%d {\n", i)
|
||||
|
||||
fmt.Fprintf(f, " return F.Pipe%d(\n", i)
|
||||
fmt.Fprintf(f, " f1(t.F1),\n")
|
||||
fmt.Fprintf(f, " fmap(tupleConstructor%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "]()),\n")
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " fap%d(f%d(t.F%d)),\n", j, j+1, j+1)
|
||||
}
|
||||
fmt.Fprintf(f, ")\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
|
||||
func generateSequenceTuple(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "\n// SequenceTuple%d is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.\n", i)
|
||||
fmt.Fprintf(f, "// The function takes a [Tuple%d] of higher higher kinded types and returns a higher kinded type of a [Tuple%d] with the resolved values.\n", i, i)
|
||||
fmt.Fprintf(f, "func SequenceTuple%d[\n", i)
|
||||
// map as the starting point
|
||||
fmt.Fprintf(f, " MAP ~func(")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "func(T%d)", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " ")
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") func(HKT_T1)")
|
||||
if i > 1 {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
@@ -71,11 +179,113 @@ func generateSequenceT(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "func(T%d) ", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
}
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d any, // HKT[", i)
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
fmt.Fprintf(f, "](\n")
|
||||
|
||||
// the callbacks
|
||||
fmt.Fprintf(f, " fmap MAP,\n")
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " fap%d AP%d,\n", j, j)
|
||||
}
|
||||
// the parameters
|
||||
fmt.Fprintf(f, " t T.Tuple%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "HKT_T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "],\n")
|
||||
fmt.Fprintf(f, ") HKT_TUPLE%d {\n", i)
|
||||
|
||||
fmt.Fprintf(f, " return F.Pipe%d(\n", i)
|
||||
fmt.Fprintf(f, " t.F1,\n")
|
||||
fmt.Fprintf(f, " fmap(tupleConstructor%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "]()),\n")
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " fap%d(t.F%d),\n", j, j+1)
|
||||
}
|
||||
fmt.Fprintf(f, ")\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
|
||||
func generateSequenceT(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "\n// SequenceT%d is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.\n", i)
|
||||
fmt.Fprintf(f, "// The function takes %d higher higher kinded types and returns a higher kinded type of a [Tuple%d] with the resolved values.\n", i, i)
|
||||
fmt.Fprintf(f, "func SequenceT%d[\n", i)
|
||||
// map as the starting point
|
||||
fmt.Fprintf(f, " MAP ~func(")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "func(T%d)", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " ")
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") func(HKT_T1)")
|
||||
if i > 1 {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := 1; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d", i)
|
||||
}
|
||||
fmt.Fprintf(f, ",\n")
|
||||
// the applicatives
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " AP%d ~func(", j)
|
||||
fmt.Fprintf(f, "HKT_T%d) func(", j+1)
|
||||
fmt.Fprintf(f, "HKT_F")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, ")")
|
||||
if j+1 < i {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := j + 1; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d", i)
|
||||
}
|
||||
fmt.Fprintf(f, ",\n")
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " T%d,\n", j+1)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " HKT_T%d, // HKT[T%d]\n", j+1, j+1)
|
||||
}
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " HKT_F")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "_T%d", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, ", // HKT[")
|
||||
for k := j; k < i; k++ {
|
||||
fmt.Fprintf(f, "func(T%d) ", k+1)
|
||||
}
|
||||
fmt.Fprintf(f, "T.")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
}
|
||||
fmt.Fprintf(f, " HKT_TUPLE%d any, // HKT[", i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "]\n")
|
||||
fmt.Fprintf(f, "](\n")
|
||||
|
||||
@@ -180,6 +390,10 @@ import (
|
||||
generateTupleConstructor(f, i)
|
||||
// sequenceT
|
||||
generateSequenceT(f, i)
|
||||
// sequenceTuple
|
||||
generateSequenceTuple(f, i)
|
||||
// traverseTuple
|
||||
generateTraverseTuple(f, i)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@@ -10,6 +10,65 @@ import (
|
||||
C "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func eitherHKT(typeE string) func(typeA string) string {
|
||||
return func(typeA string) string {
|
||||
return fmt.Sprintf("Either[%s, %s]", typeE, typeA)
|
||||
}
|
||||
}
|
||||
|
||||
func generateEitherTraverseTuple(f *os.File, i int) {
|
||||
generateTraverseTuple1(eitherHKT("E"), "E")(f, i)
|
||||
}
|
||||
|
||||
func generateEitherSequenceTuple(f *os.File, i int) {
|
||||
generateSequenceTuple1(eitherHKT("E"), "E")(f, i)
|
||||
}
|
||||
|
||||
func generateEitherSequenceT(f *os.File, i int) {
|
||||
|
||||
tuple := tupleType(i)
|
||||
|
||||
fmt.Fprintf(f, "\n// SequenceT%d converts %d parameters of [Either[E, T]] into an [Either] of a [Tuple%d].\n", i, i, i)
|
||||
fmt.Fprintf(f, "func SequenceT%d[E", i)
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, ", T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " any](")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "t%d Either[E, T%d]", j+1, j+1)
|
||||
}
|
||||
fmt.Fprintf(f, ") Either[E, %s] {\n", tuple)
|
||||
fmt.Fprintf(f, " return A.SequenceT%d(\n", i)
|
||||
// map
|
||||
fmt.Fprintf(f, " Map[E, T1,")
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " func(T%d)", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " %s],\n", tuple)
|
||||
// applicatives
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " Ap[")
|
||||
for k := j + 1; k < i; k++ {
|
||||
if k > j+1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "func(T%d)", k+1)
|
||||
}
|
||||
if j < i-1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "%s, E, T%d],\n", tuple, j+1)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " t%d,\n", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " )\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
|
||||
func generateUneitherize(f *os.File, i int) {
|
||||
// Create the optionize version
|
||||
fmt.Fprintf(f, "\n// Uneitherize%d converts a function with %d parameters returning an Either into a function with %d parameters returning a tuple\n// The inverse function is [Eitherize%d]\n", i, i, i, i)
|
||||
@@ -121,6 +180,13 @@ func generateEitherHelpers(filename string, count int) error {
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
fmt.Fprintf(f, `
|
||||
import (
|
||||
A "github.com/ibm/fp-go/internal/apply"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
`)
|
||||
|
||||
// zero level functions
|
||||
|
||||
// optionize
|
||||
@@ -133,6 +199,12 @@ func generateEitherHelpers(filename string, count int) error {
|
||||
generateEitherize(f, i)
|
||||
// unoptionize
|
||||
generateUneitherize(f, i)
|
||||
// sequenceT
|
||||
generateEitherSequenceT(f, i)
|
||||
// sequenceTuple
|
||||
generateEitherSequenceTuple(f, i)
|
||||
// traverseTuple
|
||||
generateEitherTraverseTuple(f, i)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
149
cli/monad.go
149
cli/monad.go
@@ -125,3 +125,152 @@ func monadGenerateSequenceTGeneric(
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func generateTraverseTuple1(
|
||||
hkt func(string) string,
|
||||
infix string) func(f *os.File, i int) {
|
||||
|
||||
return func(f *os.File, i int) {
|
||||
tuple := tupleType(i)
|
||||
|
||||
fmt.Fprintf(f, "\n// TraverseTuple%d converts a [Tuple%d] of [A] via transformation functions transforming [A] to [%s] into a [%s].\n", i, i, hkt("A"), hkt(fmt.Sprintf("Tuple%d", i)))
|
||||
fmt.Fprintf(f, "func TraverseTuple%d[", i)
|
||||
// functions
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "F%d ~func(A%d) %s", j+1, j+1, hkt(fmt.Sprintf("T%d", j+1)))
|
||||
}
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, ", %s", infix)
|
||||
}
|
||||
// types
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, ", A%d, T%d", j+1, j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " any](")
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "f%d F%d", j+1, j+1)
|
||||
}
|
||||
fmt.Fprintf(f, ") func (T.Tuple%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "A%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "]) %s {\n", hkt(tuple))
|
||||
fmt.Fprintf(f, " return func(t T.Tuple%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "A%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, "]) %s {\n", hkt(tuple))
|
||||
fmt.Fprintf(f, " return A.TraverseTuple%d(\n", i)
|
||||
// map
|
||||
fmt.Fprintf(f, " Map[")
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, "%s, T1,", infix)
|
||||
} else {
|
||||
fmt.Fprintf(f, "T1,")
|
||||
}
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " func(T%d)", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " %s],\n", tuple)
|
||||
// applicatives
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " Ap[")
|
||||
for k := j + 1; k < i; k++ {
|
||||
if k > j+1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "func(T%d)", k+1)
|
||||
}
|
||||
if j < i-1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "%s", tuple)
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, ", %s", infix)
|
||||
}
|
||||
fmt.Fprintf(f, ", T%d],\n", j+1)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
fmt.Fprintf(f, " f%d,\n", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " t,\n")
|
||||
fmt.Fprintf(f, " )\n")
|
||||
fmt.Fprintf(f, " }\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
}
|
||||
|
||||
func generateSequenceTuple1(
|
||||
hkt func(string) string,
|
||||
infix string) func(f *os.File, i int) {
|
||||
|
||||
return func(f *os.File, i int) {
|
||||
|
||||
tuple := tupleType(i)
|
||||
|
||||
fmt.Fprintf(f, "\n// SequenceTuple%d converts a [Tuple%d] of [%s] into an [%s].\n", i, i, hkt("T"), hkt(fmt.Sprintf("Tuple%d", i)))
|
||||
fmt.Fprintf(f, "func SequenceTuple%d[", i)
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, "%s", infix)
|
||||
}
|
||||
for j := 0; j < i; j++ {
|
||||
if infix != "" || j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " any](t T.Tuple%d[", i)
|
||||
for j := 0; j < i; j++ {
|
||||
if j > 0 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "%s", hkt(fmt.Sprintf("T%d", j+1)))
|
||||
}
|
||||
fmt.Fprintf(f, "]) %s {\n", hkt(tuple))
|
||||
fmt.Fprintf(f, " return A.SequenceTuple%d(\n", i)
|
||||
// map
|
||||
fmt.Fprintf(f, " Map[")
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, "%s, T1,", infix)
|
||||
} else {
|
||||
fmt.Fprintf(f, "T1,")
|
||||
}
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " func(T%d)", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " %s],\n", tuple)
|
||||
// applicatives
|
||||
for j := 1; j < i; j++ {
|
||||
fmt.Fprintf(f, " Ap[")
|
||||
for k := j + 1; k < i; k++ {
|
||||
if k > j+1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "func(T%d)", k+1)
|
||||
}
|
||||
if j < i-1 {
|
||||
fmt.Fprintf(f, " ")
|
||||
}
|
||||
fmt.Fprintf(f, "%s", tuple)
|
||||
if infix != "" {
|
||||
fmt.Fprintf(f, ", %s", infix)
|
||||
}
|
||||
fmt.Fprintf(f, ", T%d],\n", j+1)
|
||||
}
|
||||
fmt.Fprintf(f, " t,\n")
|
||||
fmt.Fprintf(f, " )\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,18 @@ import (
|
||||
C "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func optionHKT(typeA string) string {
|
||||
return fmt.Sprintf("Option[%s]", typeA)
|
||||
}
|
||||
|
||||
func generateOptionTraverseTuple(f *os.File, i int) {
|
||||
generateTraverseTuple1(optionHKT, "")(f, i)
|
||||
}
|
||||
|
||||
func generateOptionSequenceTuple(f *os.File, i int) {
|
||||
generateSequenceTuple1(optionHKT, "")(f, i)
|
||||
}
|
||||
|
||||
func generateOptionize(f *os.File, i int) {
|
||||
// Create the optionize version
|
||||
fmt.Fprintf(f, "\n// Optionize%d converts a function with %d parameters returning a tuple of a return value R and a boolean into a function with %d parameters returning an Option[R]\n", i, i, i)
|
||||
@@ -121,6 +133,13 @@ func generateOptionHelpers(filename string, count int) error {
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
fmt.Fprintf(f, `
|
||||
import (
|
||||
A "github.com/ibm/fp-go/internal/apply"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
`)
|
||||
|
||||
// print out some helpers
|
||||
fmt.Fprintf(f, `// optionize converts a nullary function to an option
|
||||
func optionize[R any](f func() (R, bool)) Option[R] {
|
||||
@@ -143,6 +162,10 @@ func optionize[R any](f func() (R, bool)) Option[R] {
|
||||
generateOptionize(f, i)
|
||||
// unoptionize
|
||||
generateUnoptionize(f, i)
|
||||
// sequenceTuple
|
||||
generateOptionSequenceTuple(f, i)
|
||||
// traverseTuple
|
||||
generateOptionTraverseTuple(f, i)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
89
cli/tuple.go
89
cli/tuple.go
@@ -10,17 +10,84 @@ import (
|
||||
C "github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func writeTupleType(f *os.File, i int) {
|
||||
func writeTupleType(f *os.File, symbol string, i int) {
|
||||
fmt.Fprintf(f, "Tuple%d[", i)
|
||||
for j := 1; j <= i; j++ {
|
||||
if j > 1 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T%d", j)
|
||||
fmt.Fprintf(f, "%s%d", symbol, j)
|
||||
}
|
||||
fmt.Fprintf(f, "]")
|
||||
}
|
||||
|
||||
func generateReplicate(f *os.File, i int) {
|
||||
// Create the optionize version
|
||||
fmt.Fprintf(f, "\n// Replicate%d creates a [Tuple%d] with all fields set to the input value `t`\n", i, i)
|
||||
fmt.Fprintf(f, "func Replicate%d[T any](t T) Tuple%d[", i, i)
|
||||
for j := 1; j <= i; j++ {
|
||||
if j > 1 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "T")
|
||||
}
|
||||
fmt.Fprintf(f, "] {\n")
|
||||
// execute the mapping
|
||||
fmt.Fprintf(f, " return MakeTuple%d(", i)
|
||||
for j := 1; j <= i; j++ {
|
||||
if j > 1 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "t")
|
||||
}
|
||||
fmt.Fprintf(f, ")\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
|
||||
func generateMap(f *os.File, i int) {
|
||||
// Create the optionize version
|
||||
fmt.Fprintf(f, "\n// Map%d maps each value of a [Tuple%d] via a mapping function\n", i, i)
|
||||
fmt.Fprintf(f, "func Map%d[", i)
|
||||
// function prototypes
|
||||
for j := 1; j <= i; j++ {
|
||||
if j > 1 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "F%d ~func(T%d) R%d", j, j, j)
|
||||
}
|
||||
for j := 1; j <= i; j++ {
|
||||
fmt.Fprintf(f, ", T%d, R%d", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, " any](")
|
||||
for j := 1; j <= i; j++ {
|
||||
if j > 1 {
|
||||
fmt.Fprintf(f, ", ")
|
||||
}
|
||||
fmt.Fprintf(f, "f%d F%d", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, ") func(")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") ")
|
||||
writeTupleType(f, "R", i)
|
||||
fmt.Fprintf(f, " {\n")
|
||||
|
||||
fmt.Fprintf(f, " return func(t ")
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") ")
|
||||
writeTupleType(f, "R", i)
|
||||
fmt.Fprintf(f, " {\n")
|
||||
|
||||
// execute the mapping
|
||||
fmt.Fprintf(f, " return MakeTuple%d(\n", i)
|
||||
for j := 1; j <= i; j++ {
|
||||
fmt.Fprintf(f, " f%d(t.F%d),\n", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, " )\n")
|
||||
|
||||
fmt.Fprintf(f, " }\n")
|
||||
fmt.Fprintf(f, "}\n")
|
||||
}
|
||||
|
||||
func generateMonoid(f *os.File, i int) {
|
||||
// Create the optionize version
|
||||
fmt.Fprintf(f, "\n// Monoid%d creates a [Monoid] for a [Tuple%d] based on %d monoids for the contained types\n", i, i, i)
|
||||
@@ -39,13 +106,13 @@ func generateMonoid(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "m%d M.Monoid[T%d]", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, ") M.Monoid[")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "] {\n")
|
||||
|
||||
fmt.Fprintf(f, " return M.MakeMonoid(func(l, r ")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") ")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "{\n")
|
||||
|
||||
fmt.Fprintf(f, " return MakeTuple%d(", i)
|
||||
@@ -86,11 +153,11 @@ func generateOrd(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "o%d O.Ord[T%d]", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, ") O.Ord[")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, "] {\n")
|
||||
|
||||
fmt.Fprintf(f, " return O.MakeOrd(func(l, r ")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") int {\n")
|
||||
|
||||
for j := 1; j <= i; j++ {
|
||||
@@ -98,7 +165,7 @@ func generateOrd(f *os.File, i int) {
|
||||
}
|
||||
fmt.Fprintf(f, " return 0\n")
|
||||
fmt.Fprintf(f, " }, func(l, r ")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, ") bool {\n")
|
||||
fmt.Fprintf(f, " return ")
|
||||
for j := 1; j <= i; j++ {
|
||||
@@ -148,7 +215,7 @@ func generateMakeTupleType(f *os.File, i int) {
|
||||
fmt.Fprintf(f, "t%d T%d", j, j)
|
||||
}
|
||||
fmt.Fprintf(f, ") ")
|
||||
writeTupleType(f, i)
|
||||
writeTupleType(f, "T", i)
|
||||
fmt.Fprintf(f, " {\n")
|
||||
fmt.Fprintf(f, " return Tuple%d[", i)
|
||||
for j := 1; j <= i; j++ {
|
||||
@@ -300,6 +367,10 @@ import (
|
||||
generateMonoid(f, i)
|
||||
// generate order
|
||||
generateOrd(f, i)
|
||||
// generate map
|
||||
generateMap(f, i)
|
||||
// generate replicate
|
||||
generateReplicate(f, i)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user