Skip to content

Commit

Permalink
fix: switch internal implementation of iterator from Tuple2 to Pair
Browse files Browse the repository at this point in the history
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
  • Loading branch information
CarstenLeue committed Feb 12, 2024
1 parent 51ed169 commit d0e4984
Show file tree
Hide file tree
Showing 30 changed files with 301 additions and 175 deletions.
4 changes: 2 additions & 2 deletions context/readerioeither/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
IOE "github.com/IBM/fp-go/ioeither"
IOEF "github.com/IBM/fp-go/ioeither/file"
J "github.com/IBM/fp-go/json"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

type (
Expand Down Expand Up @@ -79,7 +79,7 @@ func ReadFullResponse(client Client) func(Requester) RIOE.ReaderIOEither[H.FullR
IOE.Of[error, io.ReadCloser],
IOEF.ReadAll[io.ReadCloser],
),
IOE.Map[error](F.Bind1st(T.MakeTuple2[*http.Response, []byte], resp)),
IOE.Map[error](F.Bind1st(P.MakePair[*http.Response, []byte], resp)),
)
}),
)
Expand Down
8 changes: 4 additions & 4 deletions exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
package exec

import (
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

type (
// CommandOutput represents the output of executing a command. The first field in the [Tuple2] is
// stdout, the second one is stderr. Use [StdOut] and [StdErr] to access these fields
CommandOutput = T.Tuple2[[]byte, []byte]
CommandOutput = P.Pair[[]byte, []byte]
)

var (
// StdOut returns the field of a [CommandOutput] representing `stdout`
StdOut = T.First[[]byte, []byte]
StdOut = P.Head[[]byte, []byte]
// StdErr returns the field of a [CommandOutput] representing `stderr`
StdErr = T.Second[[]byte, []byte]
StdErr = P.Tail[[]byte, []byte]
)
8 changes: 4 additions & 4 deletions http/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ package http
import (
H "net/http"

T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

type (
// FullResponse represents a full http response, including headers and body
FullResponse = T.Tuple2[*H.Response, []byte]
FullResponse = P.Pair[*H.Response, []byte]
)

var (
Response = T.First[*H.Response, []byte]
Body = T.Second[*H.Response, []byte]
Response = P.Head[*H.Response, []byte]
Body = P.Tail[*H.Response, []byte]
)
14 changes: 6 additions & 8 deletions http/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ import (
"github.com/IBM/fp-go/errors"
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
P "github.com/IBM/fp-go/pair"
R "github.com/IBM/fp-go/record/generic"
T "github.com/IBM/fp-go/tuple"
)

type (
ParsedMediaType = T.Tuple2[string, map[string]string]
ParsedMediaType = P.Pair[string, map[string]string]

HttpError struct {
statusCode int
Expand All @@ -45,17 +45,15 @@ type (

var (
// mime type to check if a media type matches
reJSONMimeType = regexp.MustCompile(`application/(?:\w+\+)?json`)
isJSONMimeType = regexp.MustCompile(`application/(?:\w+\+)?json`).MatchString
// ValidateResponse validates an HTTP response and returns an [E.Either] if the response is not a success
ValidateResponse = E.FromPredicate(isValidStatus, StatusCodeError)
// alidateJsonContentTypeString parses a content type a validates that it is valid JSON
validateJSONContentTypeString = F.Flow2(
ParseMediaType,
E.ChainFirst(F.Flow2(
T.First[string, map[string]string],
E.FromPredicate(reJSONMimeType.MatchString, func(mimeType string) error {
return fmt.Errorf("mimetype [%s] is not a valid JSON content type", mimeType)
}),
P.Head[string, map[string]string],
E.FromPredicate(isJSONMimeType, errors.OnSome[string]("mimetype [%s] is not a valid JSON content type")),
)),
)
// ValidateJSONResponse checks if an HTTP response is a valid JSON response
Expand All @@ -81,7 +79,7 @@ const (
// ParseMediaType parses a media type into a tuple
func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
m, p, err := mime.ParseMediaType(mediaType)
return E.TryCatchError(T.MakeTuple2(m, p), err)
return E.TryCatchError(P.MakePair(m, p), err)
}

// Error fulfills the error interface
Expand Down
4 changes: 2 additions & 2 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (

EX "github.com/IBM/fp-go/exec"

T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

func Exec(ctx context.Context, name string, args []string, in []byte) (EX.CommandOutput, error) {
Expand All @@ -42,5 +42,5 @@ func Exec(ctx context.Context, name string, args []string, in []byte) (EX.Comman
err = fmt.Errorf("command execution of [%s][%s] failed, stdout [%s], stderr [%s], cause [%w]", name, args, stdOut.String(), stdErr.String(), err)
}
// return the outputs
return T.MakeTuple2(stdOut.Bytes(), stdErr.Bytes()), err
return P.MakePair(stdOut.Bytes(), stdErr.Bytes()), err
}
4 changes: 2 additions & 2 deletions ioeither/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
IOE "github.com/IBM/fp-go/ioeither"
IOEF "github.com/IBM/fp-go/ioeither/file"
J "github.com/IBM/fp-go/json"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

type (
Expand Down Expand Up @@ -95,7 +95,7 @@ func ReadFullResponse(client Client) func(Requester) IOE.IOEither[error, H.FullR
IOE.Of[error, io.ReadCloser],
IOEF.ReadAll[io.ReadCloser],
),
IOE.Map[error](F.Bind1st(T.MakeTuple2[*http.Response, []byte], resp)),
IOE.Map[error](F.Bind1st(P.MakePair[*http.Response, []byte], resp)),
)
}),
)
Expand Down
4 changes: 2 additions & 2 deletions iterator/stateless/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ package stateless

import (
G "github.com/IBM/fp-go/iterator/stateless/generic"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// Compress returns an [Iterator] that filters elements from a data [Iterator] returning only those that have a corresponding element in selector [Iterator] that evaluates to `true`.
// Stops when either the data or selectors iterator has been exhausted.
func Compress[U any](sel Iterator[bool]) func(Iterator[U]) Iterator[U] {
return G.Compress[Iterator[U], Iterator[bool], Iterator[T.Tuple2[U, bool]]](sel)
return G.Compress[Iterator[U], Iterator[bool], Iterator[P.Pair[U, bool]]](sel)
}
4 changes: 2 additions & 2 deletions iterator/stateless/generic/any.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ package generic
import (
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// Any returns `true` if any element of the iterable is `true`. If the iterable is empty, return `false`
func Any[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) bool, U any](pred FCT) func(ma GU) bool {
func Any[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) bool, U any](pred FCT) func(ma GU) bool {
return F.Flow3(
Filter[GU](pred),
First[GU],
Expand Down
14 changes: 7 additions & 7 deletions iterator/stateless/generic/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ import (
C "github.com/IBM/fp-go/internal/chain"
F "github.com/IBM/fp-go/internal/functor"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// Bind creates an empty context of type [S] to be used with the [Bind] operation
func Do[GS ~func() O.Option[T.Tuple2[GS, S]], S any](
func Do[GS ~func() O.Option[P.Pair[GS, S]], S any](
empty S,
) GS {
return Of[GS](empty)
}

// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
func Bind[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2[GS2, S2]], GA ~func() O.Option[T.Tuple2[GA, A]], S1, S2, A any](
func Bind[GS1 ~func() O.Option[P.Pair[GS1, S1]], GS2 ~func() O.Option[P.Pair[GS2, S2]], GA ~func() O.Option[P.Pair[GA, A]], S1, S2, A any](
setter func(A) func(S1) S2,
f func(S1) GA,
) func(GS1) GS2 {
Expand All @@ -45,7 +45,7 @@ func Bind[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2
}

// Let attaches the result of a computation to a context [S1] to produce a context [S2]
func Let[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2[GS2, S2]], S1, S2, A any](
func Let[GS1 ~func() O.Option[P.Pair[GS1, S1]], GS2 ~func() O.Option[P.Pair[GS2, S2]], S1, S2, A any](
key func(A) func(S1) S2,
f func(S1) A,
) func(GS1) GS2 {
Expand All @@ -57,7 +57,7 @@ func Let[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2[
}

// LetTo attaches the a value to a context [S1] to produce a context [S2]
func LetTo[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2[GS2, S2]], S1, S2, B any](
func LetTo[GS1 ~func() O.Option[P.Pair[GS1, S1]], GS2 ~func() O.Option[P.Pair[GS2, S2]], S1, S2, B any](
key func(B) func(S1) S2,
b B,
) func(GS1) GS2 {
Expand All @@ -69,7 +69,7 @@ func LetTo[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple
}

// BindTo initializes a new state [S1] from a value [T]
func BindTo[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GA ~func() O.Option[T.Tuple2[GA, A]], S1, A any](
func BindTo[GS1 ~func() O.Option[P.Pair[GS1, S1]], GA ~func() O.Option[P.Pair[GA, A]], S1, A any](
setter func(A) S1,
) func(GA) GS1 {
return C.BindTo(
Expand All @@ -79,7 +79,7 @@ func BindTo[GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GA ~func() O.Option[T.Tuple
}

// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
func ApS[GAS2 ~func() O.Option[T.Tuple2[GAS2, func(A) S2]], GS1 ~func() O.Option[T.Tuple2[GS1, S1]], GS2 ~func() O.Option[T.Tuple2[GS2, S2]], GA ~func() O.Option[T.Tuple2[GA, A]], S1, S2, A any](
func ApS[GAS2 ~func() O.Option[P.Pair[GAS2, func(A) S2]], GS1 ~func() O.Option[P.Pair[GS1, S1]], GS2 ~func() O.Option[P.Pair[GS2, S2]], GA ~func() O.Option[P.Pair[GA, A]], S1, S2, A any](
setter func(A) func(S1) S2,
fa GA,
) func(GS1) GS2 {
Expand Down
8 changes: 4 additions & 4 deletions iterator/stateless/generic/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ package generic
import (
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// Compress returns an [Iterator] that filters elements from a data [Iterator] returning only those that have a corresponding element in selector [Iterator] that evaluates to `true`.
// Stops when either the data or selectors iterator has been exhausted.
func Compress[GU ~func() O.Option[T.Tuple2[GU, U]], GB ~func() O.Option[T.Tuple2[GB, bool]], CS ~func() O.Option[T.Tuple2[CS, T.Tuple2[U, bool]]], U any](sel GB) func(GU) GU {
func Compress[GU ~func() O.Option[P.Pair[GU, U]], GB ~func() O.Option[P.Pair[GB, bool]], CS ~func() O.Option[P.Pair[CS, P.Pair[U, bool]]], U any](sel GB) func(GU) GU {
return F.Flow2(
Zip[GU, GB, CS](sel),
FilterMap[GU, CS](F.Flow2(
O.FromPredicate(T.Second[U, bool]),
O.Map(T.First[U, bool]),
O.FromPredicate(P.Tail[U, bool]),
O.Map(P.Head[U, bool]),
)),
)
}
12 changes: 6 additions & 6 deletions iterator/stateless/generic/cycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ package generic
import (
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

func Cycle[GU ~func() O.Option[T.Tuple2[GU, U]], U any](ma GU) GU {
func Cycle[GU ~func() O.Option[P.Pair[GU, U]], U any](ma GU) GU {
// avoid cyclic references
var m func(O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GU, U]]
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GU, U]]

recurse := func(mu GU) GU {
return F.Nullary2(
Expand All @@ -32,11 +32,11 @@ func Cycle[GU ~func() O.Option[T.Tuple2[GU, U]], U any](ma GU) GU {
)
}

m = O.Fold(func() O.Option[T.Tuple2[GU, U]] {
m = O.Fold(func() O.Option[P.Pair[GU, U]] {
return recurse(ma)()
}, F.Flow2(
T.Map2(recurse, F.Identity[U]),
O.Of[T.Tuple2[GU, U]],
P.BiMap(recurse, F.Identity[U]),
O.Of[P.Pair[GU, U]],
))

return recurse(ma)
Expand Down
14 changes: 7 additions & 7 deletions iterator/stateless/generic/dropwhile.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ package generic
import (
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
P "github.com/IBM/fp-go/predicate"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
PR "github.com/IBM/fp-go/predicate"
)

// DropWhile creates an [Iterator] that drops elements from the [Iterator] as long as the predicate is true; afterwards, returns every element.
// Note, the [Iterator] does not produce any output until the predicate first becomes false
func DropWhile[GU ~func() O.Option[T.Tuple2[GU, U]], U any](pred func(U) bool) func(GU) GU {
func DropWhile[GU ~func() O.Option[P.Pair[GU, U]], U any](pred func(U) bool) func(GU) GU {
// avoid cyclic references
var m func(O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GU, U]]
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GU, U]]

fromPred := O.FromPredicate(P.Not(P.ContraMap(T.Second[GU, U])(pred)))
fromPred := O.FromPredicate(PR.Not(PR.ContraMap(P.Tail[GU, U])(pred)))

recurse := func(mu GU) GU {
return F.Nullary2(
Expand All @@ -37,11 +37,11 @@ func DropWhile[GU ~func() O.Option[T.Tuple2[GU, U]], U any](pred func(U) bool) f
)
}

m = O.Chain(func(t T.Tuple2[GU, U]) O.Option[T.Tuple2[GU, U]] {
m = O.Chain(func(t P.Pair[GU, U]) O.Option[P.Pair[GU, U]] {
return F.Pipe2(
t,
fromPred,
O.Fold(recurse(Next(t)), O.Of[T.Tuple2[GU, U]]),
O.Fold(recurse(Next(t)), O.Of[P.Pair[GU, U]]),
)
})

Expand Down
6 changes: 3 additions & 3 deletions iterator/stateless/generic/first.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ package generic
import (
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// First returns the first item in an iterator if such an item exists
func First[GU ~func() O.Option[T.Tuple2[GU, U]], U any](mu GU) O.Option[U] {
func First[GU ~func() O.Option[P.Pair[GU, U]], U any](mu GU) O.Option[U] {
return F.Pipe1(
mu(),
O.Map(T.Second[GU, U]),
O.Map(P.Tail[GU, U]),
)
}
8 changes: 4 additions & 4 deletions iterator/stateless/generic/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ import (
F "github.com/IBM/fp-go/function"
L "github.com/IBM/fp-go/io/generic"
O "github.com/IBM/fp-go/option"
T "github.com/IBM/fp-go/tuple"
P "github.com/IBM/fp-go/pair"
)

// FromLazy returns an iterator on top of a lazy function
func FromLazy[GU ~func() O.Option[T.Tuple2[GU, U]], LZ ~func() U, U any](l LZ) GU {
func FromLazy[GU ~func() O.Option[P.Pair[GU, U]], LZ ~func() U, U any](l LZ) GU {
return F.Pipe1(
l,
L.Map[LZ, GU](F.Flow2(
F.Bind1st(T.MakeTuple2[GU, U], Empty[GU]()),
O.Of[T.Tuple2[GU, U]],
F.Bind1st(P.MakePair[GU, U], Empty[GU]()),
O.Of[P.Pair[GU, U]],
)),
)
}

0 comments on commit d0e4984

Please sign in to comment.