diff --git a/README.md b/README.md index 9a4c471..6494a7c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ go get github.com/IBM/fp-go Refer to the [samples](./samples/). +Find API documentation [here](https://pkg.go.dev/github.com/IBM/fp-go) + ## Design Goal This library aims to provide a set of data types and functions that make it easy and fun to write maintainable and testable code in golang. It encourages the following patterns: @@ -192,3 +194,14 @@ this would be the completely generic method signature for all possible monads. I This FP library addresses this by introducing the HKTs as individual types, e.g. `HKT[A]` would be represented as a new generic type `HKTA`. This loses the correlation to the type `A` but allows to implement generic algorithms, at the price of readability. For that reason these implementations are kept in the `internal` package. These are meant to be used by the library itself or by extensions, not by end users. + +## Map/Ap/Flap + +The following table lists the relationship between some selected operators + +| Opertator | Parameter | Monad | Result | +| -------- | ---------------- | --------------- | -------- | +| Map | `func(A) B` | `HKT[A]` | `HKT[B]` | +| Chain | `func(A) HKT[B]` | `HKT[A]` | `HKT[B]` | +| Ap | `HKT[A]` | `HKT[func(A)B]` | `HKT[B]` | +| Flap | `A` | `HKT[func(A)B]` | `HKT[B]` | diff --git a/context/readerioeither/generic/reader.go b/context/readerioeither/generic/reader.go index 41478dc..068c6ea 100644 --- a/context/readerioeither/generic/reader.go +++ b/context/readerioeither/generic/reader.go @@ -664,3 +664,11 @@ func LeftReaderIO[ A any](ma GRIOE) GRIOEA { return RIE.LeftReaderIO[GRIOEA](ma) } + +func MonadFlap[GREAB ~func(context.Context) GEAB, GREB ~func(context.Context) GEB, GEAB ~func() E.Either[error, func(A) B], GEB ~func() E.Either[error, B], B, A any](fab GREAB, a A) GREB { + return RIE.MonadFlap[GREAB, GREB](fab, a) +} + +func Flap[GREAB ~func(context.Context) GEAB, GREB ~func(context.Context) GEB, GEAB ~func() E.Either[error, func(A) B], GEB ~func() E.Either[error, B], B, A any](a A) func(GREAB) GREB { + return RIE.Flap[GREAB, GREB](a) +} diff --git a/context/readerioeither/reader.go b/context/readerioeither/reader.go index 0a31465..178b9a4 100644 --- a/context/readerioeither/reader.go +++ b/context/readerioeither/reader.go @@ -250,3 +250,11 @@ func RightReaderIO[A any](ma RIO.ReaderIO[A]) ReaderIOEither[A] { func LeftReaderIO[A any](ma RIO.ReaderIO[error]) ReaderIOEither[A] { return G.LeftReaderIO[ReaderIOEither[A]](ma) } + +func MonadFlap[B, A any](fab ReaderIOEither[func(A) B], a A) ReaderIOEither[B] { + return G.MonadFlap[ReaderIOEither[func(A) B], ReaderIOEither[B]](fab, a) +} + +func Flap[B, A any](a A) func(ReaderIOEither[func(A) B]) ReaderIOEither[B] { + return G.Flap[ReaderIOEither[func(A) B], ReaderIOEither[B]](a) +} diff --git a/ioeither/generic/ioeither.go b/ioeither/generic/ioeither.go index e88b3d2..cee7688 100644 --- a/ioeither/generic/ioeither.go +++ b/ioeither/generic/ioeither.go @@ -25,6 +25,7 @@ import ( "github.com/IBM/fp-go/internal/eithert" FE "github.com/IBM/fp-go/internal/fromeither" FI "github.com/IBM/fp-go/internal/fromio" + FC "github.com/IBM/fp-go/internal/functor" IO "github.com/IBM/fp-go/io/generic" O "github.com/IBM/fp-go/option" ) @@ -304,3 +305,11 @@ func MonadAlt[LAZY ~func() GIOA, GIOA ~func() ET.Either[E, A], E, A any](first G func Alt[LAZY ~func() GIOA, GIOA ~func() ET.Either[E, A], E, A any](second LAZY) func(GIOA) GIOA { return F.Bind2nd(MonadAlt[LAZY], second) } + +func MonadFlap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](fab GEAB, a A) GEB { + return FC.MonadFlap(MonadMap[GEAB, GEB], fab, a) +} + +func Flap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](a A) func(GEAB) GEB { + return FC.Flap(MonadMap[GEAB, GEB], a) +} diff --git a/ioeither/ioeither.go b/ioeither/ioeither.go index cfd76e6..d80780a 100644 --- a/ioeither/ioeither.go +++ b/ioeither/ioeither.go @@ -231,3 +231,11 @@ func MonadAlt[E, A any](first IOEither[E, A], second L.Lazy[IOEither[E, A]]) IOE func Alt[E, A any](second L.Lazy[IOEither[E, A]]) func(IOEither[E, A]) IOEither[E, A] { return G.Alt(second) } + +func MonadFlap[E, B, A any](fab IOEither[E, func(A) B], a A) IOEither[E, B] { + return G.MonadFlap[IOEither[E, func(A) B], IOEither[E, B]](fab, a) +} + +func Flap[E, B, A any](a A) func(IOEither[E, func(A) B]) IOEither[E, B] { + return G.Flap[IOEither[E, func(A) B], IOEither[E, B]](a) +} diff --git a/readerioeither/generic/reader.go b/readerioeither/generic/reader.go index 3c28211..22dddc8 100644 --- a/readerioeither/generic/reader.go +++ b/readerioeither/generic/reader.go @@ -24,6 +24,7 @@ import ( FIO "github.com/IBM/fp-go/internal/fromio" FIOE "github.com/IBM/fp-go/internal/fromioeither" FR "github.com/IBM/fp-go/internal/fromreader" + FC "github.com/IBM/fp-go/internal/functor" IOE "github.com/IBM/fp-go/ioeither/generic" O "github.com/IBM/fp-go/option" RD "github.com/IBM/fp-go/reader/generic" @@ -431,3 +432,11 @@ func Memoize[ GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](rdr GEA) GEA { return G.Memoize[GEA](rdr) } + +func MonadFlap[GREAB ~func(R) GEAB, GREB ~func(R) GEB, GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], R, E, B, A any](fab GREAB, a A) GREB { + return FC.MonadFlap(MonadMap[GREAB, GREB], fab, a) +} + +func Flap[GREAB ~func(R) GEAB, GREB ~func(R) GEB, GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], R, E, B, A any](a A) func(GREAB) GREB { + return FC.Flap(MonadMap[GREAB, GREB], a) +} diff --git a/readerioeither/reader.go b/readerioeither/reader.go index 79ba7c0..4c6b26c 100644 --- a/readerioeither/reader.go +++ b/readerioeither/reader.go @@ -272,3 +272,11 @@ func Memoize[ R, E, A any](rdr ReaderIOEither[R, E, A]) ReaderIOEither[R, E, A] { return G.Memoize[ReaderIOEither[R, E, A]](rdr) } + +func MonadFlap[R, E, B, A any](fab ReaderIOEither[R, E, func(A) B], a A) ReaderIOEither[R, E, B] { + return G.MonadFlap[ReaderIOEither[R, E, func(A) B], ReaderIOEither[R, E, B]](fab, a) +} + +func Flap[R, E, B, A any](a A) func(ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B] { + return G.Flap[ReaderIOEither[R, E, func(A) B], ReaderIOEither[R, E, B]](a) +}