From 9988ae27ef20a2882ab725a09d7ae00847b46538 Mon Sep 17 00:00:00 2001 From: "Dr. Carsten Leue" Date: Fri, 28 Jul 2023 15:50:03 +0200 Subject: [PATCH] fix: add support for JSON serialization on tuples Signed-off-by: Dr. Carsten Leue --- README.md | 19 +- cli/tuple.go | 196 ++++++++- context/readerioeither/gen.go | 17 +- context/readerioeither/generic/gen.go | 17 +- either/gen.go | 17 +- function/binds.go | 17 +- function/gen.go | 17 +- identity/gen.go | 17 +- internal/apply/gen.go | 17 +- io/gen.go | 17 +- io/generic/gen.go | 17 +- ioeither/gen.go | 17 +- ioeither/generic/gen.go | 17 +- iooption/gen.go | 17 +- iooption/generic/gen.go | 17 +- option/gen.go | 17 +- reader/gen.go | 17 +- reader/generic/gen.go | 17 +- readerioeither/gen.go | 17 +- readerioeither/generic/gen.go | 17 +- tuple/gen.go | 611 +++++++++++++++++++++++++- tuple/tuple_test.go | 57 +++ writer/writer_test.go | 2 +- 23 files changed, 1159 insertions(+), 32 deletions(-) create mode 100644 tuple/tuple_test.go diff --git a/README.md b/README.md index 7b6f290..6f914dd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Functional programming library for golang -**🚧 Work in progress! 🚧** Despite major version 1 because of https://github.com/semantic-release/semantic-release/issues/1507. Trying to not make breaking changes, but devil is in the details. +**🚧 Work in progress! 🚧** Despite major version 1 because of . Trying to not make breaking changes, but devil is in the details. ![logo](resources/images/logo.png) @@ -12,7 +12,7 @@ This library is strongly influenced by the awesome [fp-ts](https://github.com/gc go get github.com/IBM/fp-go ``` -Refer to the [samples](./samples/). +Refer to the [samples](./samples/). ## Design Goal @@ -65,7 +65,7 @@ This library aims to provide a set of data types and functions that make it easy #### 🧘🏽 Moderation is a virtue -✔️ The library does not implement its own goroutines and also does not require any expensive synchronization primitives. Coordination of IO operations is implemented via atomic counters without additional primitives. +✔️ The library does not implement its own goroutines and also does not require any expensive synchronization primitives. Coordination of IO operations is implemented via atomic counters without additional primitives. #### 🧘🏽 Maintainability counts @@ -87,26 +87,25 @@ If your pure function does not return an error, the idiomatic signature is just #### With Errors -If your pure function can return an error, then it will have a `(T, error)` return value in idiomatic go. In functional style the return value is [Either[error, T]](./either/) because function composition is easier with such a return type. Use the `EitherizeXXX` methods in ["github.com/IBM/fp-go/either"](./either/) to convert from idiomatic to functional style and `UneitherizeXXX` to convert from functional to idiomatic style. +If your pure function can return an error, then it will have a `(T, error)` return value in idiomatic go. In functional style the return value is [Either[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/either) because function composition is easier with such a return type. Use the `EitherizeXXX` methods in ["github.com/IBM/fp-go/either"](https://pkg.go.dev/github.com/IBM/fp-go/either) to convert from idiomatic to functional style and `UneitherizeXXX` to convert from functional to idiomatic style. ### Effectful functions -An effectful function (or function with a side effect) is one that changes data outside the scope of the function or that does not always produce the same output for the same input (because it depends on some external, mutable state). There is no special way in idiomatic go to identify such a function other than documentation. In functional style we represent them as functions that do not take an input but that produce an output. The base type for these functions is [IO[T]](./io) because in many cases such functions represent `I/O` operations. +An effectful function (or function with a side effect) is one that changes data outside the scope of the function or that does not always produce the same output for the same input (because it depends on some external, mutable state). There is no special way in idiomatic go to identify such a function other than documentation. In functional style we represent them as functions that do not take an input but that produce an output. The base type for these functions is [IO[T]](https://pkg.go.dev/github.com/IBM/fp-go/io) because in many cases such functions represent `I/O` operations. #### Without Errors -If your effectful function does not return an error, the functional signature is [IO[T]](./io) +If your effectful function does not return an error, the functional signature is [IO[T]](https://pkg.go.dev/github.com/IBM/fp-go/io) #### With Errors -If your effectful function can return an error, the functional signature is [IOEither[error, T]](./ioeither). Use `EitherizeXXX` from ["github.com/IBM/fp-go/ioeither"](./ioeither/) to convert an idiomatic go function to functional style. +If your effectful function can return an error, the functional signature is [IOEither[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/ioeither). Use `EitherizeXXX` from ["github.com/IBM/fp-go/ioeither"](https://pkg.go.dev/github.com/IBM/fp-go/ioeither) to convert an idiomatic go function to functional style. ### Go Context -Functions that take a [context](https://pkg.go.dev/context) are per definition effectful because they depend on the context parameter that is designed to be mutable (it can e.g. be used to cancel a running operation). Furthermore in idiomatic go the parameter is typically passed as the first parameter to a function. - -In functional style we isolate the [context](https://pkg.go.dev/context) and represent the nature of the effectful function as an [IOEither[error, T]](./ioeither). The resulting type is [ReaderIOEither[T]](./readerioeither), a function taking a [context](https://pkg.go.dev/context) that returns a function without parameters returning an [Either[error, T]](./either/). Use the `EitherizeXXX` methods from ["github.com/IBM/fp-go/context/readerioeither"](./context/readerioeither/) to convert an idiomatic go function with a [context](https://pkg.go.dev/context) to functional style. +Functions that take a [context](https://pkg.go.dev/context) are per definition effectful because they depend on the context parameter that is designed to be mutable (it can e.g. be used to cancel a running operation). Furthermore in idiomatic go the parameter is typically passed as the first parameter to a function. +In functional style we isolate the [context](https://pkg.go.dev/context) and represent the nature of the effectful function as an [IOEither[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/ioeither). The resulting type is [ReaderIOEither[T]](https://pkg.go.dev/github.com/IBM/fp-go/context/readerioeither), a function taking a [context](https://pkg.go.dev/context) that returns a function without parameters returning an [Either[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/either). Use the `EitherizeXXX` methods from ["github.com/IBM/fp-go/context/readerioeither"](https://pkg.go.dev/github.com/IBM/fp-go/context/readerioeither) to convert an idiomatic go function with a [context](https://pkg.go.dev/context) to functional style. ## Implementation Notes diff --git a/cli/tuple.go b/cli/tuple.go index 2df5aec..971c080 100644 --- a/cli/tuple.go +++ b/cli/tuple.go @@ -361,8 +361,10 @@ func generateTupleHelpers(filename string, count int) error { fmt.Fprintf(f, ` import ( + "fmt" + "encoding/json" M "github.com/IBM/fp-go/monoid" - O "github.com/IBM/fp-go/ord" + O "github.com/IBM/fp-go/ord" ) `) @@ -386,11 +388,203 @@ import ( generateMap(f, i) // generate replicate generateReplicate(f, i) + // generate tuple functions such as string and fmt + generateTupleString(f, i) + // generate json support + generateTupleMarshal(f, i) + // generate json support + generateTupleUnmarshal(f, i) + // generate toArray + generateToArray(f, i) + // generate fromArray + generateFromArray(f, i) } return nil } +func generateTupleMarshal(f *os.File, i int) { + // Create the stringify version + fmt.Fprintf(f, "\n// MarshalJSON marshals the [Tuple%d] into a JSON array\n", i) + fmt.Fprintf(f, "func (t ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, ") MarshalJSON() ([]byte, error) {\n") + fmt.Fprintf(f, " return json.Marshal([]any{") + // function prototypes + for j := 1; j <= i; j++ { + if j > 1 { + fmt.Fprintf(f, ", ") + } + fmt.Fprintf(f, "t.F%d", j) + } + fmt.Fprintf(f, "})\n") + fmt.Fprintf(f, "}\n") +} + +func generateTupleUnmarshal(f *os.File, i int) { + // Create the stringify version + fmt.Fprintf(f, "\n// UnmarshalJSON unmarshals a JSON array into a [Tuple%d]\n", i) + fmt.Fprintf(f, "func (t *") + writeTupleType(f, "T", i) + fmt.Fprintf(f, ") UnmarshalJSON(data []byte) error {\n") + fmt.Fprintf(f, " var tmp []json.RawMessage\n") + fmt.Fprintf(f, " if err := json.Unmarshal(data, &tmp); err != nil {return err}\n") + fmt.Fprintf(f, " l := len(tmp)\n") + // unmarshal fields + for j := 1; j <= i; j++ { + fmt.Fprintf(f, " if l > %d {\n", j-1) + fmt.Fprintf(f, " if err := json.Unmarshal(tmp[%d], &t.F%d); err != nil {return err}\n", j-1, j) + } + fmt.Fprintf(f, " ") + for j := 1; j <= i; j++ { + fmt.Fprintf(f, "}") + } + fmt.Fprintf(f, "\n return nil\n") + fmt.Fprintf(f, "}\n") +} + +func generateToArray(f *os.File, i int) { + // Create the stringify version + fmt.Fprintf(f, "\n// ToArray converts the [Tuple%d] into an array of type [R] using %d transformation functions from [T] to [R]\n// The inverse function is [FromArray%d]\n", i, i, i) + fmt.Fprintf(f, "func ToArray%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", j, j) + } + for j := 1; j <= i; j++ { + fmt.Fprintf(f, ", T%d", j) + } + fmt.Fprintf(f, ", R 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(t ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, ") []R {\n") + fmt.Fprintf(f, " return func(t ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, ") []R {\n") + fmt.Fprintf(f, " return []R{\n") + 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 generateFromArray(f *os.File, i int) { + // Create the stringify version + fmt.Fprintf(f, "\n// FromArray converts an array of [R] into a [Tuple%d] using %d functions from [R] to [T]\n// The inverse function is [ToArray%d]\n", i, i, i) + fmt.Fprintf(f, "func FromArray%d[", i) + // function prototypes + for j := 1; j <= i; j++ { + if j > 1 { + fmt.Fprintf(f, ", ") + } + fmt.Fprintf(f, "F%d ~func(R) T%d", j, j) + } + for j := 1; j <= i; j++ { + fmt.Fprintf(f, ", T%d", j) + } + fmt.Fprintf(f, ", R 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(r []R) ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, " {\n") + fmt.Fprintf(f, " return func(r []R) ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, " {\n") + fmt.Fprintf(f, " return MakeTuple%d(\n", i) + for j := 1; j <= i; j++ { + fmt.Fprintf(f, " f%d(r[%d]),\n", j, j-1) + } + fmt.Fprintf(f, " )\n") + fmt.Fprintf(f, " }\n") + fmt.Fprintf(f, "}\n") +} + +func generateTupleString(f *os.File, i int) { + // Create the stringify version + fmt.Fprintf(f, "\n// String prints some debug info for the [Tuple%d]\n", i) + fmt.Fprintf(f, "func (t ") + writeTupleType(f, "T", i) + fmt.Fprintf(f, ") String() string {\n") + // convert to string + fmt.Fprintf(f, " return fmt.Sprintf(\"Tuple%d[", i) + for j := 1; j <= i; j++ { + if j > 1 { + fmt.Fprintf(f, ", ") + } + fmt.Fprintf(f, "%s", "%T") + } + fmt.Fprintf(f, "](") + for j := 1; j <= i; j++ { + if j > 1 { + fmt.Fprintf(f, ", ") + } + fmt.Fprintf(f, "%s", "%v") + } + fmt.Fprintf(f, ")\", ") + for j := 1; j <= i; j++ { + if j > 1 { + fmt.Fprintf(f, ", ") + } + fmt.Fprintf(f, "t.F%d", j) + } + for j := 1; j <= i; j++ { + fmt.Fprintf(f, ", t.F%d", j) + } + fmt.Fprintf(f, ")\n") + fmt.Fprintf(f, "}\n") +} + +// func generateTupleJson(f *os.File, i int) { +// // Create the stringify version +// fmt.Fprintf(f, "\n// MarshalJSON converts the [Tuple%d] into a JSON byte stream\n", i) +// fmt.Fprintf(f, "func (t ") +// writeTupleType(f, "T", i) +// fmt.Fprintf(f, ") MarshalJSON() ([]byte, error) {\n") +// // convert to string +// fmt.Fprintf(f, " return fmt.Sprintf(\"Tuple%d[", i) +// for j := 1; j <= i; j++ { +// if j > 1 { +// fmt.Fprintf(f, ", ") +// } +// fmt.Fprintf(f, "%s", "%T") +// } +// fmt.Fprintf(f, "](") +// for j := 1; j <= i; j++ { +// if j > 1 { +// fmt.Fprintf(f, ", ") +// } +// fmt.Fprintf(f, "%s", "%v") +// } +// fmt.Fprintf(f, ")\", ") +// for j := 1; j <= i; j++ { +// if j > 1 { +// fmt.Fprintf(f, ", ") +// } +// fmt.Fprintf(f, "t.F%d", j) +// } +// for j := 1; j <= i; j++ { +// fmt.Fprintf(f, ", t.F%d", j) +// } +// fmt.Fprintf(f, ")\n") +// fmt.Fprintf(f, "}\n") +// } + func TupleCommand() *C.Command { return &C.Command{ Name: "tuple", diff --git a/context/readerioeither/gen.go b/context/readerioeither/gen.go index 7fdcf25..9fce20d 100644 --- a/context/readerioeither/gen.go +++ b/context/readerioeither/gen.go @@ -1,8 +1,23 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package readerioeither // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:23.9090443 +0200 CEST m=+0.018400201 +// 2023-07-28 15:42:22.8252325 +0200 CEST m=+0.010212601 import ( "context" diff --git a/context/readerioeither/generic/gen.go b/context/readerioeither/generic/gen.go index 2728a6a..607b905 100644 --- a/context/readerioeither/generic/gen.go +++ b/context/readerioeither/generic/gen.go @@ -1,8 +1,23 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package generic // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:23.9100448 +0200 CEST m=+0.019400701 +// 2023-07-28 15:42:22.8252325 +0200 CEST m=+0.010212601 import ( "context" diff --git a/either/gen.go b/either/gen.go index 1ebe8c0..fd15d99 100644 --- a/either/gen.go +++ b/either/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:26.4347269 +0200 CEST m=+0.048711601 +// 2023-07-28 15:42:24.2984201 +0200 CEST m=+0.008649601 package either diff --git a/function/binds.go b/function/binds.go index c8b0808..dfbf1bb 100644 --- a/function/binds.go +++ b/function/binds.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:37.5265731 +0200 CEST m=+0.007877601 +// 2023-07-28 15:42:51.4021911 +0200 CEST m=+0.009058101 package function // Combinations for a total of 1 arguments diff --git a/function/gen.go b/function/gen.go index 7f40fb6..6295638 100644 --- a/function/gen.go +++ b/function/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:29.4620604 +0200 CEST m=+0.015351101 +// 2023-07-28 15:42:43.1490717 +0200 CEST m=+0.010222401 package function // Pipe0 takes an initial value t0 and successively applies 0 functions where the input of a function is the return value of the previous function diff --git a/identity/gen.go b/identity/gen.go index 8903374..4c56b2b 100644 --- a/identity/gen.go +++ b/identity/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:42.4437343 +0200 CEST m=+0.033010901 +// 2023-07-28 15:42:58.8116745 +0200 CEST m=+0.008252901 package identity diff --git a/internal/apply/gen.go b/internal/apply/gen.go index aa6645c..89cbd74 100644 --- a/internal/apply/gen.go +++ b/internal/apply/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:44.3396414 +0200 CEST m=+0.008589501 +// 2023-07-28 15:43:00.6284756 +0200 CEST m=+0.013494201 package apply diff --git a/io/gen.go b/io/gen.go index 9fb22d4..27e836f 100644 --- a/io/gen.go +++ b/io/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:50.7171035 +0200 CEST m=+0.017994101 +// 2023-07-28 15:43:07.1016885 +0200 CEST m=+0.039744901 package io diff --git a/io/generic/gen.go b/io/generic/gen.go index f800ae4..66546f7 100644 --- a/io/generic/gen.go +++ b/io/generic/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:50.7191132 +0200 CEST m=+0.020003801 +// 2023-07-28 15:43:07.1026882 +0200 CEST m=+0.040744601 package generic diff --git a/ioeither/gen.go b/ioeither/gen.go index 1f3191c..13926ae 100644 --- a/ioeither/gen.go +++ b/ioeither/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:53.458059 +0200 CEST m=+0.148734701 +// 2023-07-28 15:43:09.9125541 +0200 CEST m=+0.083065801 package ioeither diff --git a/ioeither/generic/gen.go b/ioeither/generic/gen.go index a9de618..59e0ffb 100644 --- a/ioeither/generic/gen.go +++ b/ioeither/generic/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:53.4896988 +0200 CEST m=+0.180374501 +// 2023-07-28 15:43:09.9180997 +0200 CEST m=+0.088611401 package generic diff --git a/iooption/gen.go b/iooption/gen.go index 234de86..523bf64 100644 --- a/iooption/gen.go +++ b/iooption/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:57.0377326 +0200 CEST m=+0.017325101 +// 2023-07-28 15:43:14.520059 +0200 CEST m=+0.012057201 package iooption diff --git a/iooption/generic/gen.go b/iooption/generic/gen.go index 706e24e..4563a65 100644 --- a/iooption/generic/gen.go +++ b/iooption/generic/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:57.0377326 +0200 CEST m=+0.017325101 +// 2023-07-28 15:43:14.5210603 +0200 CEST m=+0.013058501 package generic diff --git a/option/gen.go b/option/gen.go index f0f12a9..43d9737 100644 --- a/option/gen.go +++ b/option/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:37:59.1632289 +0200 CEST m=+0.043384201 +// 2023-07-28 15:43:17.2891664 +0200 CEST m=+0.022524801 package option diff --git a/reader/gen.go b/reader/gen.go index b3b8917..4a3b346 100644 --- a/reader/gen.go +++ b/reader/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:38:07.286388 +0200 CEST m=+0.046901101 +// 2023-07-28 15:43:24.9416992 +0200 CEST m=+0.030259001 package reader diff --git a/reader/generic/gen.go b/reader/generic/gen.go index eb76467..1324f7e 100644 --- a/reader/generic/gen.go +++ b/reader/generic/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:38:07.2900963 +0200 CEST m=+0.050609401 +// 2023-07-28 15:43:24.9574807 +0200 CEST m=+0.046040501 package generic diff --git a/readerioeither/gen.go b/readerioeither/gen.go index 11eac38..ae7b17d 100644 --- a/readerioeither/gen.go +++ b/readerioeither/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:38:09.8136331 +0200 CEST m=+0.047621701 +// 2023-07-28 15:43:27.7019865 +0200 CEST m=+0.066240401 package readerioeither diff --git a/readerioeither/generic/gen.go b/readerioeither/generic/gen.go index 326ef78..b077186 100644 --- a/readerioeither/generic/gen.go +++ b/readerioeither/generic/gen.go @@ -1,6 +1,21 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:38:09.8196347 +0200 CEST m=+0.053623301 +// 2023-07-28 15:43:27.7039855 +0200 CEST m=+0.068239401 package generic diff --git a/tuple/gen.go b/tuple/gen.go index 5ff55ec..5519bc3 100644 --- a/tuple/gen.go +++ b/tuple/gen.go @@ -1,12 +1,29 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by go generate; DO NOT EDIT. // This file was generated by robots at -// 2023-07-27 22:38:12.6980295 +0200 CEST m=+0.011341301 +// 2023-07-28 15:43:31.1018593 +0200 CEST m=+0.128090501 package tuple import ( + "fmt" + "encoding/json" M "github.com/IBM/fp-go/monoid" - O "github.com/IBM/fp-go/ord" + O "github.com/IBM/fp-go/ord" ) // Tuple1 is a struct that carries 1 independently typed values @@ -156,6 +173,47 @@ func Replicate1[T any](t T) Tuple1[T] { return MakeTuple1(t) } +// String prints some debug info for the [Tuple1] +func (t Tuple1[T1]) String() string { + return fmt.Sprintf("Tuple1[%T](%v)", t.F1, t.F1) +} + +// MarshalJSON marshals the [Tuple1] into a JSON array +func (t Tuple1[T1]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple1] +func (t *Tuple1[T1]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + } + return nil +} + +// ToArray converts the [Tuple1] into an array of type [R] using 1 transformation functions from [T] to [R] +// The inverse function is [FromArray1] +func ToArray1[F1 ~func(T1) R, T1, R any](f1 F1) func(t Tuple1[T1]) []R { + return func(t Tuple1[T1]) []R { + return []R{ + f1(t.F1), + } + } +} + +// FromArray converts an array of [R] into a [Tuple1] using 1 functions from [R] to [T] +// The inverse function is [ToArray1] +func FromArray1[F1 ~func(R) T1, T1, R any](f1 F1) func(r []R) Tuple1[T1] { + return func(r []R) Tuple1[T1] { + return MakeTuple1( + f1(r[0]), + ) + } +} + // 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} @@ -210,6 +268,51 @@ func Replicate2[T any](t T) Tuple2[T, T] { return MakeTuple2(t, t) } +// String prints some debug info for the [Tuple2] +func (t Tuple2[T1, T2]) String() string { + return fmt.Sprintf("Tuple2[%T, %T](%v, %v)", t.F1, t.F2, t.F1, t.F2) +} + +// MarshalJSON marshals the [Tuple2] into a JSON array +func (t Tuple2[T1, T2]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple2] +func (t *Tuple2[T1, T2]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + }} + return nil +} + +// ToArray converts the [Tuple2] into an array of type [R] using 2 transformation functions from [T] to [R] +// The inverse function is [FromArray2] +func ToArray2[F1 ~func(T1) R, F2 ~func(T2) R, T1, T2, R any](f1 F1, f2 F2) func(t Tuple2[T1, T2]) []R { + return func(t Tuple2[T1, T2]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + } + } +} + +// FromArray converts an array of [R] into a [Tuple2] using 2 functions from [R] to [T] +// The inverse function is [ToArray2] +func FromArray2[F1 ~func(R) T1, F2 ~func(R) T2, T1, T2, R any](f1 F1, f2 F2) func(r []R) Tuple2[T1, T2] { + return func(r []R) Tuple2[T1, T2] { + return MakeTuple2( + f1(r[0]), + f2(r[1]), + ) + } +} + // 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} @@ -266,6 +369,55 @@ func Replicate3[T any](t T) Tuple3[T, T, T] { return MakeTuple3(t, t, t) } +// String prints some debug info for the [Tuple3] +func (t Tuple3[T1, T2, T3]) String() string { + return fmt.Sprintf("Tuple3[%T, %T, %T](%v, %v, %v)", t.F1, t.F2, t.F3, t.F1, t.F2, t.F3) +} + +// MarshalJSON marshals the [Tuple3] into a JSON array +func (t Tuple3[T1, T2, T3]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple3] +func (t *Tuple3[T1, T2, T3]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + }}} + return nil +} + +// ToArray converts the [Tuple3] into an array of type [R] using 3 transformation functions from [T] to [R] +// The inverse function is [FromArray3] +func ToArray3[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, T1, T2, T3, R any](f1 F1, f2 F2, f3 F3) func(t Tuple3[T1, T2, T3]) []R { + return func(t Tuple3[T1, T2, T3]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + } + } +} + +// FromArray converts an array of [R] into a [Tuple3] using 3 functions from [R] to [T] +// The inverse function is [ToArray3] +func FromArray3[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, T1, T2, T3, R any](f1 F1, f2 F2, f3 F3) func(r []R) Tuple3[T1, T2, T3] { + return func(r []R) Tuple3[T1, T2, T3] { + return MakeTuple3( + f1(r[0]), + f2(r[1]), + f3(r[2]), + ) + } +} + // 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} @@ -324,6 +476,59 @@ func Replicate4[T any](t T) Tuple4[T, T, T, T] { return MakeTuple4(t, t, t, t) } +// String prints some debug info for the [Tuple4] +func (t Tuple4[T1, T2, T3, T4]) String() string { + return fmt.Sprintf("Tuple4[%T, %T, %T, %T](%v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F1, t.F2, t.F3, t.F4) +} + +// MarshalJSON marshals the [Tuple4] into a JSON array +func (t Tuple4[T1, T2, T3, T4]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple4] +func (t *Tuple4[T1, T2, T3, T4]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + }}}} + return nil +} + +// ToArray converts the [Tuple4] into an array of type [R] using 4 transformation functions from [T] to [R] +// The inverse function is [FromArray4] +func ToArray4[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, T1, T2, T3, T4, R any](f1 F1, f2 F2, f3 F3, f4 F4) func(t Tuple4[T1, T2, T3, T4]) []R { + return func(t Tuple4[T1, T2, T3, T4]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + } + } +} + +// FromArray converts an array of [R] into a [Tuple4] using 4 functions from [R] to [T] +// The inverse function is [ToArray4] +func FromArray4[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, T1, T2, T3, T4, R any](f1 F1, f2 F2, f3 F3, f4 F4) func(r []R) Tuple4[T1, T2, T3, T4] { + return func(r []R) Tuple4[T1, T2, T3, T4] { + return MakeTuple4( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + ) + } +} + // 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} @@ -384,6 +589,63 @@ func Replicate5[T any](t T) Tuple5[T, T, T, T, T] { return MakeTuple5(t, t, t, t, t) } +// String prints some debug info for the [Tuple5] +func (t Tuple5[T1, T2, T3, T4, T5]) String() string { + return fmt.Sprintf("Tuple5[%T, %T, %T, %T, %T](%v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F1, t.F2, t.F3, t.F4, t.F5) +} + +// MarshalJSON marshals the [Tuple5] into a JSON array +func (t Tuple5[T1, T2, T3, T4, T5]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple5] +func (t *Tuple5[T1, T2, T3, T4, T5]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + }}}}} + return nil +} + +// ToArray converts the [Tuple5] into an array of type [R] using 5 transformation functions from [T] to [R] +// The inverse function is [FromArray5] +func ToArray5[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, T1, T2, T3, T4, T5, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(t Tuple5[T1, T2, T3, T4, T5]) []R { + return func(t Tuple5[T1, T2, T3, T4, T5]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + } + } +} + +// FromArray converts an array of [R] into a [Tuple5] using 5 functions from [R] to [T] +// The inverse function is [ToArray5] +func FromArray5[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, T1, T2, T3, T4, T5, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(r []R) Tuple5[T1, T2, T3, T4, T5] { + return func(r []R) Tuple5[T1, T2, T3, T4, T5] { + return MakeTuple5( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + ) + } +} + // 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} @@ -446,6 +708,67 @@ func Replicate6[T any](t T) Tuple6[T, T, T, T, T, T] { return MakeTuple6(t, t, t, t, t, t) } +// String prints some debug info for the [Tuple6] +func (t Tuple6[T1, T2, T3, T4, T5, T6]) String() string { + return fmt.Sprintf("Tuple6[%T, %T, %T, %T, %T, %T](%v, %v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F1, t.F2, t.F3, t.F4, t.F5, t.F6) +} + +// MarshalJSON marshals the [Tuple6] into a JSON array +func (t Tuple6[T1, T2, T3, T4, T5, T6]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5, t.F6}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple6] +func (t *Tuple6[T1, T2, T3, T4, T5, T6]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + if l > 5 { + if err := json.Unmarshal(tmp[5], &t.F6); err != nil {return err} + }}}}}} + return nil +} + +// ToArray converts the [Tuple6] into an array of type [R] using 6 transformation functions from [T] to [R] +// The inverse function is [FromArray6] +func ToArray6[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, T1, T2, T3, T4, T5, T6, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(t Tuple6[T1, T2, T3, T4, T5, T6]) []R { + return func(t Tuple6[T1, T2, T3, T4, T5, T6]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + f6(t.F6), + } + } +} + +// FromArray converts an array of [R] into a [Tuple6] using 6 functions from [R] to [T] +// The inverse function is [ToArray6] +func FromArray6[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, T1, T2, T3, T4, T5, T6, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(r []R) Tuple6[T1, T2, T3, T4, T5, T6] { + return func(r []R) Tuple6[T1, T2, T3, T4, T5, T6] { + return MakeTuple6( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + f6(r[5]), + ) + } +} + // 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} @@ -510,6 +833,71 @@ func Replicate7[T any](t T) Tuple7[T, T, T, T, T, T, T] { return MakeTuple7(t, t, t, t, t, t, t) } +// String prints some debug info for the [Tuple7] +func (t Tuple7[T1, T2, T3, T4, T5, T6, T7]) String() string { + return fmt.Sprintf("Tuple7[%T, %T, %T, %T, %T, %T, %T](%v, %v, %v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7) +} + +// MarshalJSON marshals the [Tuple7] into a JSON array +func (t Tuple7[T1, T2, T3, T4, T5, T6, T7]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple7] +func (t *Tuple7[T1, T2, T3, T4, T5, T6, T7]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + if l > 5 { + if err := json.Unmarshal(tmp[5], &t.F6); err != nil {return err} + if l > 6 { + if err := json.Unmarshal(tmp[6], &t.F7); err != nil {return err} + }}}}}}} + return nil +} + +// ToArray converts the [Tuple7] into an array of type [R] using 7 transformation functions from [T] to [R] +// The inverse function is [FromArray7] +func ToArray7[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, T1, T2, T3, T4, T5, T6, T7, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(t Tuple7[T1, T2, T3, T4, T5, T6, T7]) []R { + return func(t Tuple7[T1, T2, T3, T4, T5, T6, T7]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + f6(t.F6), + f7(t.F7), + } + } +} + +// FromArray converts an array of [R] into a [Tuple7] using 7 functions from [R] to [T] +// The inverse function is [ToArray7] +func FromArray7[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, T1, T2, T3, T4, T5, T6, T7, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(r []R) Tuple7[T1, T2, T3, T4, T5, T6, T7] { + return func(r []R) Tuple7[T1, T2, T3, T4, T5, T6, T7] { + return MakeTuple7( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + f6(r[5]), + f7(r[6]), + ) + } +} + // 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} @@ -576,6 +964,75 @@ func Replicate8[T any](t T) Tuple8[T, T, T, T, T, T, T, T] { return MakeTuple8(t, t, t, t, t, t, t, t) } +// String prints some debug info for the [Tuple8] +func (t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) String() string { + return fmt.Sprintf("Tuple8[%T, %T, %T, %T, %T, %T, %T, %T](%v, %v, %v, %v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8) +} + +// MarshalJSON marshals the [Tuple8] into a JSON array +func (t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple8] +func (t *Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + if l > 5 { + if err := json.Unmarshal(tmp[5], &t.F6); err != nil {return err} + if l > 6 { + if err := json.Unmarshal(tmp[6], &t.F7); err != nil {return err} + if l > 7 { + if err := json.Unmarshal(tmp[7], &t.F8); err != nil {return err} + }}}}}}}} + return nil +} + +// ToArray converts the [Tuple8] into an array of type [R] using 8 transformation functions from [T] to [R] +// The inverse function is [FromArray8] +func ToArray8[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, T1, T2, T3, T4, T5, T6, T7, T8, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) []R { + return func(t Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]) []R { + return []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + f6(t.F6), + f7(t.F7), + f8(t.F8), + } + } +} + +// FromArray converts an array of [R] into a [Tuple8] using 8 functions from [R] to [T] +// The inverse function is [ToArray8] +func FromArray8[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, T1, T2, T3, T4, T5, T6, T7, T8, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(r []R) Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] { + return func(r []R) Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] { + return MakeTuple8( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + f6(r[5]), + f7(r[6]), + f8(r[7]), + ) + } +} + // 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} @@ -644,6 +1101,79 @@ func Replicate9[T any](t T) Tuple9[T, T, T, T, T, T, T, T, T] { return MakeTuple9(t, t, t, t, t, t, t, t, t) } +// String prints some debug info for the [Tuple9] +func (t Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) String() string { + return fmt.Sprintf("Tuple9[%T, %T, %T, %T, %T, %T, %T, %T, %T](%v, %v, %v, %v, %v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9) +} + +// MarshalJSON marshals the [Tuple9] into a JSON array +func (t Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple9] +func (t *Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + if l > 5 { + if err := json.Unmarshal(tmp[5], &t.F6); err != nil {return err} + if l > 6 { + if err := json.Unmarshal(tmp[6], &t.F7); err != nil {return err} + if l > 7 { + if err := json.Unmarshal(tmp[7], &t.F8); err != nil {return err} + if l > 8 { + if err := json.Unmarshal(tmp[8], &t.F9); err != nil {return err} + }}}}}}}}} + return nil +} + +// ToArray converts the [Tuple9] into an array of type [R] using 9 transformation functions from [T] to [R] +// The inverse function is [FromArray9] +func ToArray9[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(t 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 []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + f6(t.F6), + f7(t.F7), + f8(t.F8), + f9(t.F9), + } + } +} + +// FromArray converts an array of [R] into a [Tuple9] using 9 functions from [R] to [T] +// The inverse function is [ToArray9] +func FromArray9[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(r []R) Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { + return func(r []R) Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { + return MakeTuple9( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + f6(r[5]), + f7(r[6]), + f8(r[7]), + f9(r[8]), + ) + } +} + // 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} @@ -713,3 +1243,80 @@ func Map10[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F func Replicate10[T any](t T) Tuple10[T, T, T, T, T, T, T, T, T, T] { return MakeTuple10(t, t, t, t, t, t, t, t, t, t) } + +// String prints some debug info for the [Tuple10] +func (t Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) String() string { + return fmt.Sprintf("Tuple10[%T, %T, %T, %T, %T, %T, %T, %T, %T, %T](%v, %v, %v, %v, %v, %v, %v, %v, %v, %v)", t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10) +} + +// MarshalJSON marshals the [Tuple10] into a JSON array +func (t Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) MarshalJSON() ([]byte, error) { + return json.Marshal([]any{t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10}) +} + +// UnmarshalJSON unmarshals a JSON array into a [Tuple10] +func (t *Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) UnmarshalJSON(data []byte) error { + var tmp []json.RawMessage + if err := json.Unmarshal(data, &tmp); err != nil {return err} + l := len(tmp) + if l > 0 { + if err := json.Unmarshal(tmp[0], &t.F1); err != nil {return err} + if l > 1 { + if err := json.Unmarshal(tmp[1], &t.F2); err != nil {return err} + if l > 2 { + if err := json.Unmarshal(tmp[2], &t.F3); err != nil {return err} + if l > 3 { + if err := json.Unmarshal(tmp[3], &t.F4); err != nil {return err} + if l > 4 { + if err := json.Unmarshal(tmp[4], &t.F5); err != nil {return err} + if l > 5 { + if err := json.Unmarshal(tmp[5], &t.F6); err != nil {return err} + if l > 6 { + if err := json.Unmarshal(tmp[6], &t.F7); err != nil {return err} + if l > 7 { + if err := json.Unmarshal(tmp[7], &t.F8); err != nil {return err} + if l > 8 { + if err := json.Unmarshal(tmp[8], &t.F9); err != nil {return err} + if l > 9 { + if err := json.Unmarshal(tmp[9], &t.F10); err != nil {return err} + }}}}}}}}}} + return nil +} + +// ToArray converts the [Tuple10] into an array of type [R] using 10 transformation functions from [T] to [R] +// The inverse function is [FromArray10] +func ToArray10[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(t 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 []R{ + f1(t.F1), + f2(t.F2), + f3(t.F3), + f4(t.F4), + f5(t.F5), + f6(t.F6), + f7(t.F7), + f8(t.F8), + f9(t.F9), + f10(t.F10), + } + } +} + +// FromArray converts an array of [R] into a [Tuple10] using 10 functions from [R] to [T] +// The inverse function is [ToArray10] +func FromArray10[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(r []R) Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { + return func(r []R) Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { + return MakeTuple10( + f1(r[0]), + f2(r[1]), + f3(r[2]), + f4(r[3]), + f5(r[4]), + f6(r[5]), + f7(r[6]), + f8(r[7]), + f9(r[8]), + f10(r[9]), + ) + } +} diff --git a/tuple/tuple_test.go b/tuple/tuple_test.go new file mode 100644 index 0000000..51018a2 --- /dev/null +++ b/tuple/tuple_test.go @@ -0,0 +1,57 @@ +// Copyright (c) 2023 IBM Corp. +// All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tuple + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestString(t *testing.T) { + + value := MakeTuple2("Carsten", 1) + + assert.Equal(t, "Tuple2[string, int](Carsten, 1)", value.String()) + +} + +func TestMarshal(t *testing.T) { + + value := MakeTuple3("Carsten", 1, true) + + data, err := json.Marshal(value) + require.NoError(t, err) + + var unmarshaled Tuple3[string, int, bool] + err = json.Unmarshal(data, &unmarshaled) + require.NoError(t, err) + + assert.Equal(t, value, unmarshaled) +} + +func TestMarshalSmallArray(t *testing.T) { + + value := `["Carsten"]` + + var unmarshaled Tuple3[string, int, bool] + err := json.Unmarshal([]byte(value), &unmarshaled) + require.NoError(t, err) + + assert.Equal(t, MakeTuple3("Carsten", 0, false), unmarshaled) +} diff --git a/writer/writer_test.go b/writer/writer_test.go index 6326be5..cda61b2 100644 --- a/writer/writer_test.go +++ b/writer/writer_test.go @@ -45,6 +45,6 @@ func ExampleLoggingWriter() { fmt.Println(res()) - // Output: {40 [Doubled 10 -> 20 Doubled 20 -> 40]} + // Output: Tuple2[int, []string](40, [Doubled 10 -> 20 Doubled 20 -> 40]) }