diff --git a/array/array.go b/array/array.go index 9cda781..a9b154c 100644 --- a/array/array.go +++ b/array/array.go @@ -308,3 +308,11 @@ func Fold[A any](m M.Monoid[A]) func([]A) A { func Push[A any](a A) func([]A) []A { return G.Push[[]A](a) } + +func MonadFlap[A, B any](fab []func(A) B, a A) []B { + return G.MonadFlap[func(A) B, []func(A) B, []B, A, B](fab, a) +} + +func Flap[A, B any](a A) func([]func(A) B) []B { + return G.Flap[func(A) B, []func(A) B, []B, A, B](a) +} diff --git a/array/generic/array.go b/array/generic/array.go index a0fb83b..3ff3bd0 100644 --- a/array/generic/array.go +++ b/array/generic/array.go @@ -18,6 +18,7 @@ package generic import ( F "github.com/IBM/fp-go/function" "github.com/IBM/fp-go/internal/array" + FC "github.com/IBM/fp-go/internal/functor" M "github.com/IBM/fp-go/monoid" O "github.com/IBM/fp-go/option" "github.com/IBM/fp-go/tuple" @@ -250,3 +251,11 @@ func Fold[AS ~[]A, A any](m M.Monoid[A]) func(AS) A { func Push[GA ~[]A, A any](a A) func(GA) GA { return F.Bind2nd(array.Push[GA, A], a) } + +func MonadFlap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](fab GFAB, a A) GB { + return FC.MonadFlap(MonadMap[GFAB, GB], fab, a) +} + +func Flap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](a A) func(GFAB) GB { + return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a) +} diff --git a/array/nonempty/array.go b/array/nonempty/array.go new file mode 100644 index 0000000..b72962f --- /dev/null +++ b/array/nonempty/array.go @@ -0,0 +1,105 @@ +// 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 nonempty + +import ( + G "github.com/IBM/fp-go/array/generic" + F "github.com/IBM/fp-go/function" + "github.com/IBM/fp-go/internal/array" +) + +// NonEmptyArray represents an array with at least one element +type NonEmptyArray[A any] []A + +// Of constructs a single element array +func Of[A any](first A) NonEmptyArray[A] { + return G.Of[NonEmptyArray[A]](first) +} + +// From constructs an array from a set of variadic arguments +func From[A any](first A, data ...A) NonEmptyArray[A] { + count := len(data) + if count == 0 { + return Of(first) + } + // allocate the requested buffer + buffer := make(NonEmptyArray[A], count+1) + buffer[0] = first + copy(buffer[1:], data) + return buffer +} + +func IsEmpty[A any](as NonEmptyArray[A]) bool { + return false +} + +func IsNonEmpty[A any](as NonEmptyArray[A]) bool { + return true +} + +func MonadMap[A, B any](as NonEmptyArray[A], f func(a A) B) NonEmptyArray[B] { + return G.MonadMap[NonEmptyArray[A], NonEmptyArray[B]](as, f) +} + +func Map[A, B any](f func(a A) B) func(NonEmptyArray[A]) NonEmptyArray[B] { + return F.Bind2nd(MonadMap[A, B], f) +} + +func Reduce[A, B any](f func(B, A) B, initial B) func(NonEmptyArray[A]) B { + return func(as NonEmptyArray[A]) B { + return array.Reduce(as, f, initial) + } +} + +func Tail[A any](as NonEmptyArray[A]) []A { + return as[1:] +} + +func Head[A any](as NonEmptyArray[A]) A { + return as[0] +} + +func First[A any](as NonEmptyArray[A]) A { + return as[0] +} + +func Last[A any](as NonEmptyArray[A]) A { + return as[len(as)-1] +} + +func Size[A any](as NonEmptyArray[A]) int { + return G.Size(as) +} + +func Flatten[A any](mma NonEmptyArray[NonEmptyArray[A]]) NonEmptyArray[A] { + return G.Flatten(mma) +} + +func MonadChain[A, B any](fa NonEmptyArray[A], f func(a A) NonEmptyArray[B]) NonEmptyArray[B] { + return G.MonadChain[NonEmptyArray[A], NonEmptyArray[B]](fa, f) +} + +func Chain[A, B any](f func(A) NonEmptyArray[B]) func(NonEmptyArray[A]) NonEmptyArray[B] { + return G.Chain[NonEmptyArray[A], NonEmptyArray[B]](f) +} + +func MonadAp[B, A any](fab NonEmptyArray[func(A) B], fa NonEmptyArray[A]) NonEmptyArray[B] { + return G.MonadAp[NonEmptyArray[B]](fab, fa) +} + +func Ap[B, A any](fa NonEmptyArray[A]) func(NonEmptyArray[func(A) B]) NonEmptyArray[B] { + return G.Ap[NonEmptyArray[B], NonEmptyArray[func(A) B]](fa) +} diff --git a/either/either.go b/either/either.go index cdced1f..2dd5542 100644 --- a/either/either.go +++ b/either/either.go @@ -22,6 +22,7 @@ package either import ( E "github.com/IBM/fp-go/errors" F "github.com/IBM/fp-go/function" + FC "github.com/IBM/fp-go/internal/functor" O "github.com/IBM/fp-go/option" ) @@ -245,3 +246,11 @@ func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 func Swap[E, A any](val Either[E, A]) Either[A, E] { return MonadFold(val, Right[A, E], Left[E, A]) } + +func MonadFlap[E, A, B any](fab Either[E, func(A) B], a A) Either[E, B] { + return FC.MonadFlap(MonadMap[E, func(A) B, B], fab, a) +} + +func Flap[E, A, B any](a A) func(Either[E, func(A) B]) Either[E, B] { + return F.Bind2nd(MonadFlap[E, A, B], a) +} diff --git a/identity/generic/identity.go b/identity/generic/identity.go index d0a6595..83dba8a 100644 --- a/identity/generic/identity.go +++ b/identity/generic/identity.go @@ -18,6 +18,7 @@ package generic import ( F "github.com/IBM/fp-go/function" C "github.com/IBM/fp-go/internal/chain" + FC "github.com/IBM/fp-go/internal/functor" ) func MonadAp[GAB ~func(A) B, B, A any](fab GAB, fa A) B { @@ -51,3 +52,11 @@ func MonadChainFirst[GAB ~func(A) B, A, B any](fa A, f GAB) A { func ChainFirst[GAB ~func(A) B, A, B any](f GAB) func(A) A { return C.ChainFirst(MonadChain[func(A) A, A, A], MonadMap[func(B) A, B, A], f) } + +func MonadFlap[GAB ~func(A) B, A, B any](fab GAB, a A) B { + return FC.MonadFlap(MonadMap[func(GAB) B, GAB, B], fab, a) +} + +func Flap[GAB ~func(A) B, A, B any](a A) func(GAB) B { + return F.Bind2nd(MonadFlap[GAB, A, B], a) +} diff --git a/identity/identity.go b/identity/identity.go index 4af3052..9fcd6c7 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -63,3 +63,11 @@ func MonadChainFirst[A, B any](fa A, f func(A) B) A { func ChainFirst[A, B any](f func(A) B) func(A) A { return G.ChainFirst(f) } + +func MonadFlap[A, B any](fab func(A) B, a A) B { + return G.MonadFlap[func(A) B](fab, a) +} + +func Flap[A, B any](a A) func(func(A) B) B { + return G.Flap[func(A) B](a) +} diff --git a/internal/functor/flap.go b/internal/functor/flap.go new file mode 100644 index 0000000..c83e8d9 --- /dev/null +++ b/internal/functor/flap.go @@ -0,0 +1,37 @@ +// 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 functor + +func MonadFlap[FAB ~func(A) B, A, B, HKTFAB, HKTB any]( + fmap func(HKTFAB, func(FAB) B) HKTB, + + fab HKTFAB, + a A, +) HKTB { + return fmap(fab, func(f FAB) B { + return f(a) + }) +} + +func Flap[FAB ~func(A) B, A, B, HKTFAB, HKTB any]( + fmap func(HKTFAB, func(FAB) B) HKTB, + + a A, +) func(HKTFAB) HKTB { + return func(fab HKTFAB) HKTB { + return MonadFlap(fmap, fab, a) + } +} diff --git a/io/generic/io.go b/io/generic/io.go index 024476b..71a0d68 100644 --- a/io/generic/io.go +++ b/io/generic/io.go @@ -20,6 +20,7 @@ import ( F "github.com/IBM/fp-go/function" C "github.com/IBM/fp-go/internal/chain" + FC "github.com/IBM/fp-go/internal/functor" L "github.com/IBM/fp-go/internal/lazy" ) @@ -143,3 +144,11 @@ func Defer[GA ~func() A, A any](gen func() GA) GA { return gen()() }) } + +func MonadFlap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](fab GFAB, a A) GB { + return FC.MonadFlap(MonadMap[GFAB, GB, FAB, B], fab, a) +} + +func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(GFAB) GB { + return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a) +} diff --git a/io/io.go b/io/io.go index 0e0b71e..2fbf64d 100644 --- a/io/io.go +++ b/io/io.go @@ -138,3 +138,11 @@ var Now = G.Now[IO[time.Time]]() func Defer[A any](gen func() IO[A]) IO[A] { return G.Defer[IO[A]](gen) } + +func MonadFlap[A, B any](fab IO[func(A) B], a A) IO[B] { + return G.MonadFlap[func(A) B, IO[func(A) B], IO[B], A, B](fab, a) +} + +func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(IO[func(A) B]) IO[B] { + return G.Flap[func(A) B, IO[func(A) B], IO[B], A, B](a) +} diff --git a/option/option.go b/option/option.go index 145a681..f45ea93 100644 --- a/option/option.go +++ b/option/option.go @@ -18,6 +18,7 @@ package option import ( F "github.com/IBM/fp-go/function" + FC "github.com/IBM/fp-go/internal/functor" ) func fromPredicate[A any](a A, pred func(A) bool) Option[A] { @@ -141,3 +142,11 @@ func Reduce[A, B any](f func(B, A) B, initial B) func(Option[A]) B { func Filter[A any](pred func(A) bool) func(Option[A]) Option[A] { return Fold(None[A], F.Ternary(pred, Of[A], F.Ignore1of1[A](None[A]))) } + +func MonadFlap[A, B any](fab Option[func(A) B], a A) Option[B] { + return FC.MonadFlap(MonadMap[func(A) B, B], fab, a) +} + +func Flap[A, B any](a A) func(Option[func(A) B]) Option[B] { + return F.Bind2nd(MonadFlap[A, B], a) +}