diff --git a/record/record.go b/record/record.go index 7354d04..7bebd1f 100644 --- a/record/record.go +++ b/record/record.go @@ -98,7 +98,7 @@ func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) func(map[K]V) map[ } // Lookup returns the entry for a key in a map if it exists -func Lookup[K comparable, V any](k K) func(map[K]V) O.Option[V] { +func Lookup[V any, K comparable](k K) func(map[K]V) O.Option[V] { return G.Lookup[map[K]V](k) } diff --git a/record/record_test.go b/record/record_test.go index c2f5a58..07d2699 100644 --- a/record/record_test.go +++ b/record/record_test.go @@ -71,8 +71,8 @@ func TestLookup(t *testing.T) { "b": "b", "c": "c", } - assert.Equal(t, O.Some("a"), Lookup[string, string]("a")(data)) - assert.Equal(t, O.None[string](), Lookup[string, string]("a1")(data)) + assert.Equal(t, O.Some("a"), Lookup[string]("a")(data)) + assert.Equal(t, O.None[string](), Lookup[string]("a1")(data)) } func TestFilterChain(t *testing.T) { diff --git a/types/array.go b/types/array.go deleted file mode 100644 index b533ee5..0000000 --- a/types/array.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 types - -import ( - "fmt" - "reflect" - - AR "github.com/IBM/fp-go/array/generic" - E "github.com/IBM/fp-go/either" - F "github.com/IBM/fp-go/function" - T "github.com/IBM/fp-go/tuple" -) - -func toUnknownArray[A any](item func(reflect.Value, Context) E.Either[Errors, A], c Context, val reflect.Value) []E.Either[Errors, A] { - l := val.Len() - res := make([]E.Either[Errors, A], l) - for i := l - 1; i >= 0; i-- { - v := val.Index(i) - res[i] = item(v, AR.Push[Context](&ContextEntry{Key: fmt.Sprintf("[%d]", i), Value: v})(c)) - } - return res -} - -func flattenUnknownArray[GA ~[]A, A any](as []E.Either[Errors, A]) E.Either[Errors, GA] { - return F.Pipe1( - AR.Reduce(as, func(t T.Tuple2[GA, Errors], item E.Either[Errors, A]) T.Tuple2[GA, Errors] { - return E.MonadFold(item, func(e Errors) T.Tuple2[GA, Errors] { - return T.MakeTuple2(t.F1, append(t.F2, e...)) - }, func(a A) T.Tuple2[GA, Errors] { - return T.MakeTuple2(append(t.F1, a), t.F2) - }) - }, T.MakeTuple2(make(GA, len(as)), make(Errors, 0))), - func(t T.Tuple2[GA, Errors]) E.Either[Errors, GA] { - if AR.IsEmpty(t.F2) { - return E.Of[Errors](t.F1) - } - return E.Left[GA](t.F2) - }, - ) -} - -func toValidatedArray[GA ~[]A, A any](item func(reflect.Value, Context) E.Either[Errors, A], c Context, val reflect.Value) E.Either[Errors, GA] { - return F.Pipe1( - toUnknownArray(item, c, val), - flattenUnknownArray[GA, A], - ) -} - -func validateArray[GA ~[]A, A any](item Validate[reflect.Value, A]) func(i reflect.Value, c Context) E.Either[Errors, GA] { - var r func(i reflect.Value, c Context) E.Either[Errors, GA] - - r = func(i reflect.Value, c Context) E.Either[Errors, GA] { - // check for unknow array - switch i.Kind() { - case reflect.Slice: - return toValidatedArray[GA](item, c, i) - case reflect.Array: - return toValidatedArray[GA](item, c, i) - case reflect.Pointer: - return r(i.Elem(), c) - default: - return Failure[GA](c, fmt.Sprintf("Type %T is neither an array nor a slice nor a pointer to these values", i)) - } - } - - return r -} - -// ArrayG returns the type validator for an array -func ArrayG[GA ~[]A, A any](item Validate[reflect.Value, A]) *Type[GA, GA, reflect.Value] { - return FromValidate(validateArray[GA, A](item)) -} - -// Array returns the type validator for an array -func Array[A any](item Validate[reflect.Value, A]) *Type[[]A, []A, reflect.Value] { - return ArrayG[[]A, A](item) -} diff --git a/types/array_test.go b/types/array_test.go deleted file mode 100644 index 73c4709..0000000 --- a/types/array_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// 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 types - -import ( - "reflect" - "testing" - - A "github.com/IBM/fp-go/array" - E "github.com/IBM/fp-go/either" - "github.com/stretchr/testify/assert" -) - -func TestArray(t *testing.T) { - stringArray := Array(String.Validate) - - validData := A.From( - reflect.ValueOf(A.From("a", "b", "c")), - reflect.ValueOf(A.Empty[string]()), - reflect.ValueOf([]string{"a", "b"}), - reflect.ValueOf(A.From(1, 2, 3)), - ) - - for i := 0; i < len(validData); i++ { - assert.True(t, E.IsRight(stringArray.Decode(validData[i]))) - } - -} diff --git a/types/kleisli.go b/types/kleisli.go deleted file mode 100644 index c24492f..0000000 --- a/types/kleisli.go +++ /dev/null @@ -1,16 +0,0 @@ -// 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 types diff --git a/types/pathreporter.go b/types/pathreporter.go deleted file mode 100644 index 211e088..0000000 --- a/types/pathreporter.go +++ /dev/null @@ -1,39 +0,0 @@ -// 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 types - -import ( - AR "github.com/IBM/fp-go/array/generic" - E "github.com/IBM/fp-go/either" -) - -func getMessage(val *ValidationError) string { - return val.Message -} - -func pathNoErrors() []string { - return AR.Of[[]string]("No Errors!") -} - -func PathReporter[A any](val E.Either[Errors, A]) []string { - return E.MonadFold( - val, - AR.Map[Errors, []string](getMessage), - func(_ A) []string { - return pathNoErrors() - }, - ) -} diff --git a/types/string.go b/types/string.go deleted file mode 100644 index d332335..0000000 --- a/types/string.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 types - -import ( - "fmt" - "reflect" - "strconv" - - E "github.com/IBM/fp-go/either" -) - -func validateStringFromReflect(i reflect.Value, c Context) E.Either[Errors, string] { - switch i.Kind() { - case reflect.String: - return E.Of[Errors](i.String()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return E.Of[Errors](strconv.FormatInt(i.Int(), 10)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return E.Of[Errors](strconv.FormatUint(i.Uint(), 10)) - case reflect.Bool: - return E.Of[Errors](strconv.FormatBool(i.Bool())) - case reflect.Pointer: - return validateStringFromReflect(i.Elem(), c) - case reflect.Invalid: - return Failure[string](c, "Invalid value") - } - - if i.CanInterface() { - if strg, ok := i.Interface().(fmt.Stringer); ok { - return E.Of[Errors](strg.String()) - } - } - - return E.Of[Errors](i.String()) -} - -// String returns the type validator for a string -func makeString() *Type[string, string, reflect.Value] { - return FromValidate(validateStringFromReflect) -} - -// converts from any type to string -var String = makeString() diff --git a/types/string_test.go b/types/string_test.go deleted file mode 100644 index bd4e059..0000000 --- a/types/string_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 types - -import ( - "reflect" - "testing" - - A "github.com/IBM/fp-go/array" - E "github.com/IBM/fp-go/either" - "github.com/stretchr/testify/assert" -) - -func TestString(t *testing.T) { - s := "Carsten" - validData := A.From( - reflect.ValueOf("Carsten"), - reflect.ValueOf(s), - reflect.ValueOf(&s), - reflect.ValueOf(10), - reflect.ValueOf(true), - reflect.ValueOf(false), - ) - for i := 0; i < len(validData); i++ { - assert.True(t, E.IsRight(String.Decode(validData[i]))) - } - - invalidDataData := A.From( - reflect.ValueOf(nil), - ) - for i := 0; i < len(invalidDataData); i++ { - assert.True(t, E.IsLeft(String.Decode(invalidDataData[i]))) - } -} diff --git a/types/types.go b/types/types.go deleted file mode 100644 index a14ade8..0000000 --- a/types/types.go +++ /dev/null @@ -1,146 +0,0 @@ -// 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 types - -import ( - AR "github.com/IBM/fp-go/array/generic" - E "github.com/IBM/fp-go/either" - F "github.com/IBM/fp-go/function" - "github.com/IBM/fp-go/option" -) - -type ( - ValidationError struct { - Context Context - Message string - } - - ContextEntry struct { - Key string - Value any - } - - Errors []*ValidationError - - Context []*ContextEntry - - Encoder[A, O any] interface { - Encode(A) O - } - - Decoder[I, A any] interface { - Validate(I, Context) E.Either[Errors, A] - Decode(I) E.Either[Errors, A] - } - - Codec[I, O, A any] interface { - Encoder[A, O] - Decoder[I, A] - } - - Guard[I, A any] func(I) option.Option[A] - - Validate[I, A any] func(I, Context) E.Either[Errors, A] - - Type[A, O, I any] struct { - validate func(I, Context) E.Either[Errors, A] - encode func(A) O - is Guard[I, A] - } -) - -func (t *Type[A, O, I]) Validate(i I, c Context) E.Either[Errors, A] { - return t.validate(i, c) -} - -func defaultContext(value any) Context { - return AR.Of[Context](&ContextEntry{Value: value}) -} - -func (t *Type[A, O, I]) Decode(i I) E.Either[Errors, A] { - return t.validate(i, defaultContext(i)) -} - -func (t *Type[A, O, I]) Encode(a A) O { - return t.encode(a) -} - -func (t *Type[A, O, I]) Is(a I) option.Option[A] { - return t.is(a) -} - -func (t *Type[A, O, I]) AsEncoder() Encoder[A, O] { - return t -} - -func (t *Type[A, O, I]) AsDecoder() Decoder[I, A] { - return t -} - -func (val *ValidationError) Error() string { - return val.Message -} - -func Pipe[O, I, A, B any](ab Type[B, A, A]) func(a Type[A, O, I]) Type[B, O, I] { - return func(a Type[A, O, I]) Type[B, O, I] { - return Type[B, O, I]{ - is: F.Flow2( - a.is, - option.Chain(ab.Is), - ), - validate: func(i I, c Context) E.Either[Errors, B] { - return F.Pipe1( - a.Validate(i, c), - E.Chain(F.Bind2nd(ab.Validate, c)), - ) - }, - encode: F.Flow2( - ab.Encode, - a.Encode, - ), - } - } -} - -func Success[A any](value A) E.Either[Errors, A] { - return E.Of[Errors](value) -} - -func Failures[A any](err Errors) E.Either[Errors, A] { - return E.Left[A](err) -} - -func Failure[A any](c Context, message string) E.Either[Errors, A] { - return Failures[A](AR.Of[Errors](&ValidationError{Context: c, Message: message})) -} - -func guardFromValidate[A, I any](validate func(I, Context) E.Either[Errors, A]) Guard[I, A] { - return func(i I) option.Option[A] { - return F.Pipe1( - validate(i, defaultContext(i)), - E.ToOption[Errors, A], - ) - } -} - -// FromValidate constructs a Type instance from just the validation function -func FromValidate[A, I any](validate Validate[I, A]) *Type[A, A, I] { - return &Type[A, A, I]{ - validate, - F.Identity[A], - guardFromValidate[A, I](validate), - } -}