mirror of
https://github.com/IBM/fp-go.git
synced 2025-09-03 20:06:08 +02:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f4f4fb306c | ||
|
747f477a96 | ||
|
045f4e8849 | ||
|
65e09e0e90 | ||
|
6ab6ff094b | ||
|
e6e35d643c | ||
|
01d490b710 | ||
|
01786a054b | ||
|
d0e4984b60 |
@@ -26,7 +26,7 @@ import (
|
|||||||
IOE "github.com/IBM/fp-go/ioeither"
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
IOEF "github.com/IBM/fp-go/ioeither/file"
|
IOEF "github.com/IBM/fp-go/ioeither/file"
|
||||||
J "github.com/IBM/fp-go/json"
|
J "github.com/IBM/fp-go/json"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -79,7 +79,7 @@ func ReadFullResponse(client Client) func(Requester) RIOE.ReaderIOEither[H.FullR
|
|||||||
IOE.Of[error, io.ReadCloser],
|
IOE.Of[error, io.ReadCloser],
|
||||||
IOEF.ReadAll[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)),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
@@ -16,18 +16,18 @@
|
|||||||
package exec
|
package exec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// CommandOutput represents the output of executing a command. The first field in the [Tuple2] is
|
// 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
|
// 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 (
|
var (
|
||||||
// StdOut returns the field of a [CommandOutput] representing `stdout`
|
// 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 returns the field of a [CommandOutput] representing `stderr`
|
||||||
StdErr = T.Second[[]byte, []byte]
|
StdErr = P.Tail[[]byte, []byte]
|
||||||
)
|
)
|
||||||
|
@@ -18,15 +18,15 @@ package http
|
|||||||
import (
|
import (
|
||||||
H "net/http"
|
H "net/http"
|
||||||
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// FullResponse represents a full http response, including headers and body
|
// FullResponse represents a full http response, including headers and body
|
||||||
FullResponse = T.Tuple2[*H.Response, []byte]
|
FullResponse = P.Pair[*H.Response, []byte]
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Response = T.First[*H.Response, []byte]
|
Response = P.Head[*H.Response, []byte]
|
||||||
Body = T.Second[*H.Response, []byte]
|
Body = P.Tail[*H.Response, []byte]
|
||||||
)
|
)
|
||||||
|
@@ -28,12 +28,12 @@ import (
|
|||||||
"github.com/IBM/fp-go/errors"
|
"github.com/IBM/fp-go/errors"
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
R "github.com/IBM/fp-go/record/generic"
|
R "github.com/IBM/fp-go/record/generic"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ParsedMediaType = T.Tuple2[string, map[string]string]
|
ParsedMediaType = P.Pair[string, map[string]string]
|
||||||
|
|
||||||
HttpError struct {
|
HttpError struct {
|
||||||
statusCode int
|
statusCode int
|
||||||
@@ -45,17 +45,15 @@ type (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// mime type to check if a media type matches
|
// 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 validates an HTTP response and returns an [E.Either] if the response is not a success
|
||||||
ValidateResponse = E.FromPredicate(isValidStatus, StatusCodeError)
|
ValidateResponse = E.FromPredicate(isValidStatus, StatusCodeError)
|
||||||
// alidateJsonContentTypeString parses a content type a validates that it is valid JSON
|
// alidateJsonContentTypeString parses a content type a validates that it is valid JSON
|
||||||
validateJSONContentTypeString = F.Flow2(
|
validateJSONContentTypeString = F.Flow2(
|
||||||
ParseMediaType,
|
ParseMediaType,
|
||||||
E.ChainFirst(F.Flow2(
|
E.ChainFirst(F.Flow2(
|
||||||
T.First[string, map[string]string],
|
P.Head[string, map[string]string],
|
||||||
E.FromPredicate(reJSONMimeType.MatchString, func(mimeType string) error {
|
E.FromPredicate(isJSONMimeType, errors.OnSome[string]("mimetype [%s] is not a valid JSON content type")),
|
||||||
return fmt.Errorf("mimetype [%s] is not a valid JSON content type", mimeType)
|
|
||||||
}),
|
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
// ValidateJSONResponse checks if an HTTP response is a valid JSON response
|
// ValidateJSONResponse checks if an HTTP response is a valid JSON response
|
||||||
@@ -81,7 +79,7 @@ const (
|
|||||||
// ParseMediaType parses a media type into a tuple
|
// ParseMediaType parses a media type into a tuple
|
||||||
func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
|
func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
|
||||||
m, p, err := mime.ParseMediaType(mediaType)
|
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
|
// Error fulfills the error interface
|
||||||
|
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
EX "github.com/IBM/fp-go/exec"
|
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) {
|
func Exec(ctx context.Context, name string, args []string, in []byte) (EX.CommandOutput, error) {
|
||||||
@@ -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)
|
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 the outputs
|
||||||
return T.MakeTuple2(stdOut.Bytes(), stdErr.Bytes()), err
|
return P.MakePair(stdOut.Bytes(), stdErr.Bytes()), err
|
||||||
}
|
}
|
||||||
|
198
internal/statet/state.go
Normal file
198
internal/statet/state.go
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
// Copyright (c) 2024 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Of[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTA,
|
||||||
|
S, A any,
|
||||||
|
](
|
||||||
|
fof func(P.Pair[A, S]) HKTA,
|
||||||
|
|
||||||
|
a A) HKTSA {
|
||||||
|
|
||||||
|
return F.Flow2(
|
||||||
|
F.Bind1st(P.MakePair[A, S], a),
|
||||||
|
fof,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMap[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
S, A, B any,
|
||||||
|
](
|
||||||
|
fmap func(HKTA, func(P.Pair[A, S]) P.Pair[B, S]) HKTB,
|
||||||
|
|
||||||
|
fa HKTSA,
|
||||||
|
f func(A) B,
|
||||||
|
) HKTSB {
|
||||||
|
|
||||||
|
return F.Flow2(
|
||||||
|
fa,
|
||||||
|
F.Bind2nd(fmap, P.Map[S](f)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
S, A, B any,
|
||||||
|
](
|
||||||
|
fmap func(func(P.Pair[A, S]) P.Pair[B, S]) func(HKTA) HKTB,
|
||||||
|
|
||||||
|
f func(A) B,
|
||||||
|
) func(HKTSA) HKTSB {
|
||||||
|
mp := fmap(P.Map[S](f))
|
||||||
|
|
||||||
|
return func(fa HKTSA) HKTSB {
|
||||||
|
return F.Flow2(
|
||||||
|
fa,
|
||||||
|
mp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
S, A any,
|
||||||
|
](
|
||||||
|
fchain func(HKTA, func(P.Pair[A, S]) HKTB) HKTB,
|
||||||
|
|
||||||
|
fa HKTSA,
|
||||||
|
f func(A) HKTSB,
|
||||||
|
) HKTSB {
|
||||||
|
return F.Flow2(
|
||||||
|
fa,
|
||||||
|
F.Bind2nd(fchain, func(a P.Pair[A, S]) HKTB {
|
||||||
|
return f(P.Head(a))(P.Tail(a))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
S, A any,
|
||||||
|
](
|
||||||
|
fchain func(func(P.Pair[A, S]) HKTB) func(HKTA) HKTB,
|
||||||
|
|
||||||
|
f func(A) HKTSB,
|
||||||
|
) func(HKTSA) HKTSB {
|
||||||
|
mp := fchain(func(a P.Pair[A, S]) HKTB {
|
||||||
|
return f(P.Head(a))(P.Tail(a))
|
||||||
|
})
|
||||||
|
|
||||||
|
return func(fa HKTSA) HKTSB {
|
||||||
|
return F.Flow2(
|
||||||
|
fa,
|
||||||
|
mp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadAp[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTSAB ~func(S) HKTAB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
HKTAB,
|
||||||
|
|
||||||
|
S, A, B any,
|
||||||
|
](
|
||||||
|
fmap func(HKTA, func(P.Pair[A, S]) P.Pair[B, S]) HKTB,
|
||||||
|
fchain func(HKTAB, func(P.Pair[func(A) B, S]) HKTB) HKTB,
|
||||||
|
|
||||||
|
fab HKTSAB,
|
||||||
|
fa HKTSA,
|
||||||
|
) HKTSB {
|
||||||
|
return func(s S) HKTB {
|
||||||
|
return fchain(fab(s), func(ab P.Pair[func(A) B, S]) HKTB {
|
||||||
|
return fmap(fa(P.Tail(ab)), P.Map[S](P.Head(ab)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ap[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTSB ~func(S) HKTB,
|
||||||
|
HKTSAB ~func(S) HKTAB,
|
||||||
|
HKTA,
|
||||||
|
HKTB,
|
||||||
|
HKTAB,
|
||||||
|
|
||||||
|
S, A, B any,
|
||||||
|
](
|
||||||
|
fmap func(func(P.Pair[A, S]) P.Pair[B, S]) func(HKTA) HKTB,
|
||||||
|
fchain func(func(P.Pair[func(A) B, S]) HKTB) func(HKTAB) HKTB,
|
||||||
|
|
||||||
|
fa HKTSA,
|
||||||
|
) func(HKTSAB) HKTSB {
|
||||||
|
return func(fab HKTSAB) HKTSB {
|
||||||
|
return F.Flow2(
|
||||||
|
fab,
|
||||||
|
fchain(func(ab P.Pair[func(A) B, S]) HKTB {
|
||||||
|
return fmap(P.Map[S](P.Head(ab)))(fa(P.Tail(ab)))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromF[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
HKTA,
|
||||||
|
|
||||||
|
HKTFA,
|
||||||
|
|
||||||
|
S, A any,
|
||||||
|
](
|
||||||
|
fmap func(HKTFA, func(A) P.Pair[A, S]) HKTA,
|
||||||
|
ma HKTFA) HKTSA {
|
||||||
|
|
||||||
|
f1 := F.Bind1st(fmap, ma)
|
||||||
|
|
||||||
|
return func(s S) HKTA {
|
||||||
|
return f1(F.Bind2nd(P.MakePair[A, S], s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromState[
|
||||||
|
HKTSA ~func(S) HKTA,
|
||||||
|
ST ~func(S) P.Pair[A, S],
|
||||||
|
HKTA,
|
||||||
|
|
||||||
|
S, A any,
|
||||||
|
](
|
||||||
|
fof func(P.Pair[A, S]) HKTA,
|
||||||
|
sa ST,
|
||||||
|
) HKTSA {
|
||||||
|
return F.Flow2(sa, fof)
|
||||||
|
}
|
@@ -27,16 +27,11 @@ const (
|
|||||||
|
|
||||||
// MonadApSeq implements the applicative on a single thread by first executing mab and the ma
|
// MonadApSeq implements the applicative on a single thread by first executing mab and the ma
|
||||||
func MonadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
func MonadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
||||||
return MakeIO[GB](func() B {
|
return MonadChain(mab, F.Bind1st(MonadMap[GA, GB], ma))
|
||||||
return F.Pipe1(
|
|
||||||
ma(),
|
|
||||||
mab(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadApPar implements the applicative on two threads, the main thread executes mab and the actuall
|
// MonadApPar implements the applicative on two threads, the main thread executes mab and the actuall
|
||||||
// apply operation and the second thred computes ma. Communication between the threads happens via a channel
|
// apply operation and the second thread computes ma. Communication between the threads happens via a channel
|
||||||
func MonadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
func MonadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
|
||||||
return MakeIO[GB](func() B {
|
return MakeIO[GB](func() B {
|
||||||
c := make(chan A)
|
c := make(chan A)
|
||||||
|
@@ -32,6 +32,28 @@ func MonadTraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadTraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
|
||||||
|
return RA.MonadTraverse(
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApSeq[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
tas,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadTraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
|
||||||
|
return RA.MonadTraverse(
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApPar[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
tas,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
|
func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
|
||||||
return RA.Traverse[AAS](
|
return RA.Traverse[AAS](
|
||||||
Of[GBS, BBS],
|
Of[GBS, BBS],
|
||||||
@@ -42,6 +64,26 @@ func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
|
||||||
|
return RA.Traverse[AAS](
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApSeq[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
|
||||||
|
return RA.Traverse[AAS](
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApPar[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
|
func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
|
||||||
return RA.TraverseWithIndex[AAS](
|
return RA.TraverseWithIndex[AAS](
|
||||||
Of[GBS, BBS],
|
Of[GBS, BBS],
|
||||||
@@ -52,10 +94,38 @@ func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TraverseArrayWithIndexSeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
|
||||||
|
return RA.TraverseWithIndex[AAS](
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApSeq[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TraverseArrayWithIndexPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
|
||||||
|
return RA.TraverseWithIndex[AAS](
|
||||||
|
Of[GBS, BBS],
|
||||||
|
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
|
||||||
|
ApPar[GBS, func() func(B) BBS, GB],
|
||||||
|
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
|
func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
|
||||||
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
|
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SequenceArraySeq[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
|
||||||
|
return MonadTraverseArraySeq[GA, GAS](tas, F.Identity[GA])
|
||||||
|
}
|
||||||
|
|
||||||
|
func SequenceArrayPar[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
|
||||||
|
return MonadTraverseArrayPar[GA, GAS](tas, F.Identity[GA])
|
||||||
|
}
|
||||||
|
|
||||||
// MonadTraverseRecord transforms a record using an IO transform an IO of a record
|
// MonadTraverseRecord transforms a record using an IO transform an IO of a record
|
||||||
func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||||
return RR.MonadTraverse[MA](
|
return RR.MonadTraverse[MA](
|
||||||
@@ -89,3 +159,71 @@ func TraverseRecordWithIndex[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[
|
|||||||
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
||||||
return MonadTraverseRecord[GAS](tas, F.Identity[GA])
|
return MonadTraverseRecord[GAS](tas, F.Identity[GA])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MonadTraverseRecordSeq transforms a record using an IO transform an IO of a record
|
||||||
|
func MonadTraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||||
|
return RR.MonadTraverse[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApSeq[GBS, func() func(B) MB, GB],
|
||||||
|
ma, f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecordSeq transforms a record using an IO transform an IO of a record
|
||||||
|
func TraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
|
||||||
|
return RR.Traverse[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApSeq[GBS, func() func(B) MB, GB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecordWithIndexSeq transforms a record using an IO transform an IO of a record
|
||||||
|
func TraverseRecordWithIndexSeq[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
|
||||||
|
return RR.TraverseWithIndex[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApSeq[GBS, func() func(B) MB, GB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SequenceRecordSeq[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
||||||
|
return MonadTraverseRecordSeq[GAS](tas, F.Identity[GA])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MonadTraverseRecordPar transforms a record using an IO transform an IO of a record
|
||||||
|
func MonadTraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||||
|
return RR.MonadTraverse[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApPar[GBS, func() func(B) MB, GB],
|
||||||
|
ma, f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecordPar transforms a record using an IO transform an IO of a record
|
||||||
|
func TraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
|
||||||
|
return RR.Traverse[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApPar[GBS, func() func(B) MB, GB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecordWithIndexPar transforms a record using an IO transform an IO of a record
|
||||||
|
func TraverseRecordWithIndexPar[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
|
||||||
|
return RR.TraverseWithIndex[MA](
|
||||||
|
Of[GBS, MB],
|
||||||
|
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||||
|
ApPar[GBS, func() func(B) MB, GB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SequenceRecordPar[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
||||||
|
return MonadTraverseRecordPar[GAS](tas, F.Identity[GA])
|
||||||
|
}
|
||||||
|
47
io/sequence_test.go
Normal file
47
io/sequence_test.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// 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 io
|
||||||
|
|
||||||
|
import (
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapSeq(t *testing.T) {
|
||||||
|
var results []string
|
||||||
|
|
||||||
|
handler := func(value string) IO[string] {
|
||||||
|
return func() string {
|
||||||
|
results = append(results, value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src := A.From("a", "b", "c")
|
||||||
|
|
||||||
|
res := F.Pipe2(
|
||||||
|
src,
|
||||||
|
TraverseArraySeq(handler),
|
||||||
|
Map(func(data []string) bool {
|
||||||
|
return assert.Equal(t, data, results)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.True(t, res())
|
||||||
|
}
|
@@ -60,3 +60,45 @@ func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) IO[B]) func(ma
|
|||||||
func SequenceRecord[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
|
func SequenceRecord[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
|
||||||
return G.SequenceRecord[IO[A], IO[map[K]A]](tas)
|
return G.SequenceRecord[IO[A], IO[map[K]A]](tas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadTraverseArraySeq[A, B any](tas []A, f func(A) IO[B]) IO[[]B] {
|
||||||
|
return G.MonadTraverseArraySeq[IO[B], IO[[]B]](tas, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseArraySeq applies a function returning an [IO] to all elements in an array and the
|
||||||
|
// transforms this into an [IO] of that array
|
||||||
|
func TraverseArraySeq[A, B any](f func(A) IO[B]) func([]A) IO[[]B] {
|
||||||
|
return G.TraverseArraySeq[IO[B], IO[[]B], []A](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseArrayWithIndexSeq applies a function returning an [IO] to all elements in an array and the
|
||||||
|
// transforms this into an [IO] of that array
|
||||||
|
func TraverseArrayWithIndexSeq[A, B any](f func(int, A) IO[B]) func([]A) IO[[]B] {
|
||||||
|
return G.TraverseArrayWithIndexSeq[IO[B], IO[[]B], []A](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SequenceArraySeq converts an array of [IO] to an [IO] of an array
|
||||||
|
func SequenceArraySeq[A any](tas []IO[A]) IO[[]A] {
|
||||||
|
return G.SequenceArraySeq[IO[A], IO[[]A]](tas)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadTraverseRecordSeq[K comparable, A, B any](tas map[K]A, f func(A) IO[B]) IO[map[K]B] {
|
||||||
|
return G.MonadTraverseRecordSeq[IO[map[K]B]](tas, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecord applies a function returning an [IO] to all elements in a record and the
|
||||||
|
// transforms this into an [IO] of that record
|
||||||
|
func TraverseRecordSeq[K comparable, A, B any](f func(A) IO[B]) func(map[K]A) IO[map[K]B] {
|
||||||
|
return G.TraverseRecordSeq[IO[map[K]B], map[K]A, IO[B]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraverseRecordWithIndexSeq applies a function returning an [IO] to all elements in a record and the
|
||||||
|
// transforms this into an [IO] of that record
|
||||||
|
func TraverseRecordWithIndeSeq[K comparable, A, B any](f func(K, A) IO[B]) func(map[K]A) IO[map[K]B] {
|
||||||
|
return G.TraverseRecordWithIndexSeq[IO[B], IO[map[K]B], map[K]A](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SequenceRecordSeq converts a record of [IO] to an [IO] of a record
|
||||||
|
func SequenceRecordSeq[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
|
||||||
|
return G.SequenceRecordSeq[IO[A], IO[map[K]A]](tas)
|
||||||
|
}
|
||||||
|
56
ioeither/generic/monad.go
Normal file
56
ioeither/generic/monad.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ioEitherPointed[E, A any, GA ~func() ET.Either[E, A]] struct{}
|
||||||
|
|
||||||
|
type ioEitherMonad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]] struct{}
|
||||||
|
|
||||||
|
func (o *ioEitherPointed[E, A, GA]) Of(a A) GA {
|
||||||
|
return Of[GA, E, A](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Of(a A) GA {
|
||||||
|
return Of[GA, E, A](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GA, GB, E, A, B](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Chain(f func(A) GB) func(GA) GB {
|
||||||
|
return Chain[GA, GB, E, A, B](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB {
|
||||||
|
return Ap[GB, GAB, GA, E, A, B](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [IOEither]
|
||||||
|
func Pointed[E, A any, GA ~func() ET.Either[E, A]]() pointed.Pointed[A, GA] {
|
||||||
|
return &ioEitherPointed[E, A, GA]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [IOEither]
|
||||||
|
func Monad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]]() monad.Monad[A, B, GA, GB, GAB] {
|
||||||
|
return &ioEitherMonad[E, A, B, GA, GB, GAB]{}
|
||||||
|
}
|
@@ -27,7 +27,7 @@ import (
|
|||||||
IOE "github.com/IBM/fp-go/ioeither"
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
IOEF "github.com/IBM/fp-go/ioeither/file"
|
IOEF "github.com/IBM/fp-go/ioeither/file"
|
||||||
J "github.com/IBM/fp-go/json"
|
J "github.com/IBM/fp-go/json"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -95,7 +95,7 @@ func ReadFullResponse(client Client) func(Requester) IOE.IOEither[error, H.FullR
|
|||||||
IOE.Of[error, io.ReadCloser],
|
IOE.Of[error, io.ReadCloser],
|
||||||
IOEF.ReadAll[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)),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
32
ioeither/monad.go
Normal file
32
ioeither/monad.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2024 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 ioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
G "github.com/IBM/fp-go/ioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pointed returns the pointed operations for [IOEither]
|
||||||
|
func Pointed[E, A any]() pointed.Pointed[A, IOEither[E, A]] {
|
||||||
|
return G.Pointed[E, A, IOEither[E, A]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad returns the monadic operations for [IOEither]
|
||||||
|
func Monad[E, A, B any]() monad.Monad[A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]] {
|
||||||
|
return G.Monad[E, A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]]()
|
||||||
|
}
|
48
ioeither/sequence_test.go
Normal file
48
ioeither/sequence_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// 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 ioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapSeq(t *testing.T) {
|
||||||
|
var results []string
|
||||||
|
|
||||||
|
handler := func(value string) IOEither[error, string] {
|
||||||
|
return func() E.Either[error, string] {
|
||||||
|
results = append(results, value)
|
||||||
|
return E.Of[error](value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src := A.From("a", "b", "c")
|
||||||
|
|
||||||
|
res := F.Pipe2(
|
||||||
|
src,
|
||||||
|
TraverseArraySeq(handler),
|
||||||
|
Map[error](func(data []string) bool {
|
||||||
|
return assert.Equal(t, data, results)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.Equal(t, E.Of[error](true), res())
|
||||||
|
}
|
@@ -17,11 +17,11 @@ package stateless
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
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`.
|
// 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.
|
// Stops when either the data or selectors iterator has been exhausted.
|
||||||
func Compress[U any](sel Iterator[bool]) func(Iterator[U]) Iterator[U] {
|
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)
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,11 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
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`
|
// 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(
|
return F.Flow3(
|
||||||
Filter[GU](pred),
|
Filter[GU](pred),
|
||||||
First[GU],
|
First[GU],
|
||||||
|
@@ -20,18 +20,18 @@ import (
|
|||||||
C "github.com/IBM/fp-go/internal/chain"
|
C "github.com/IBM/fp-go/internal/chain"
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
F "github.com/IBM/fp-go/internal/functor"
|
||||||
O "github.com/IBM/fp-go/option"
|
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
|
// 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,
|
empty S,
|
||||||
) GS {
|
) GS {
|
||||||
return Of[GS](empty)
|
return Of[GS](empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
// 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,
|
setter func(A) func(S1) S2,
|
||||||
f func(S1) GA,
|
f func(S1) GA,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
@@ -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]
|
// 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,
|
key func(A) func(S1) S2,
|
||||||
f func(S1) A,
|
f func(S1) A,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
@@ -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]
|
// 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,
|
key func(B) func(S1) S2,
|
||||||
b B,
|
b B,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
@@ -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]
|
// 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,
|
setter func(A) S1,
|
||||||
) func(GA) GS1 {
|
) func(GA) GS1 {
|
||||||
return C.BindTo(
|
return C.BindTo(
|
||||||
@@ -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
|
// 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,
|
setter func(A) func(S1) S2,
|
||||||
fa GA,
|
fa GA,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
|
@@ -18,17 +18,17 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
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`.
|
// 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.
|
// 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(
|
return F.Flow2(
|
||||||
Zip[GU, GB, CS](sel),
|
Zip[GU, GB, CS](sel),
|
||||||
FilterMap[GU, CS](F.Flow2(
|
FilterMap[GU, CS](F.Flow2(
|
||||||
O.FromPredicate(T.Second[U, bool]),
|
O.FromPredicate(P.Tail[U, bool]),
|
||||||
O.Map(T.First[U, bool]),
|
O.Map(P.Head[U, bool]),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -18,12 +18,12 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
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
|
// 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 {
|
recurse := func(mu GU) GU {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -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)()
|
return recurse(ma)()
|
||||||
}, F.Flow2(
|
}, F.Flow2(
|
||||||
T.Map2(recurse, F.Identity[U]),
|
P.BiMap(recurse, F.Identity[U]),
|
||||||
O.Of[T.Tuple2[GU, U]],
|
O.Of[P.Pair[GU, U]],
|
||||||
))
|
))
|
||||||
|
|
||||||
return recurse(ma)
|
return recurse(ma)
|
||||||
|
@@ -18,17 +18,17 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
P "github.com/IBM/fp-go/predicate"
|
P "github.com/IBM/fp-go/pair"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
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.
|
// 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
|
// 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
|
// 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 {
|
recurse := func(mu GU) GU {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -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(
|
return F.Pipe2(
|
||||||
t,
|
t,
|
||||||
fromPred,
|
fromPred,
|
||||||
O.Fold(recurse(Next(t)), O.Of[T.Tuple2[GU, U]]),
|
O.Fold(recurse(Next(t)), O.Of[P.Pair[GU, U]]),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -18,13 +18,13 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
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
|
// 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(
|
return F.Pipe1(
|
||||||
mu(),
|
mu(),
|
||||||
O.Map(T.Second[GU, U]),
|
O.Map(P.Tail[GU, U]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -19,16 +19,16 @@ import (
|
|||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
L "github.com/IBM/fp-go/io/generic"
|
L "github.com/IBM/fp-go/io/generic"
|
||||||
O "github.com/IBM/fp-go/option"
|
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
|
// 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(
|
return F.Pipe1(
|
||||||
l,
|
l,
|
||||||
L.Map[LZ, GU](F.Flow2(
|
L.Map[LZ, GU](F.Flow2(
|
||||||
F.Bind1st(T.MakeTuple2[GU, U], Empty[GU]()),
|
F.Bind1st(P.MakePair[GU, U], Empty[GU]()),
|
||||||
O.Of[T.Tuple2[GU, U]],
|
O.Of[P.Pair[GU, U]],
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -24,45 +24,45 @@ import (
|
|||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
N "github.com/IBM/fp-go/number"
|
N "github.com/IBM/fp-go/number"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Next returns the iterator for the next element in an iterator `T.Tuple2`
|
// Next returns the iterator for the next element in an iterator `P.Pair`
|
||||||
func Next[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m T.Tuple2[GU, U]) GU {
|
func Next[GU ~func() O.Option[P.Pair[GU, U]], U any](m P.Pair[GU, U]) GU {
|
||||||
return T.First(m)
|
return P.Head(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current returns the current element in an iterator `T.Tuple2`
|
// Current returns the current element in an iterator `P.Pair`
|
||||||
func Current[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m T.Tuple2[GU, U]) U {
|
func Current[GU ~func() O.Option[P.Pair[GU, U]], U any](m P.Pair[GU, U]) U {
|
||||||
return T.Second(m)
|
return P.Tail(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// From constructs an array from a set of variadic arguments
|
// From constructs an array from a set of variadic arguments
|
||||||
func From[GU ~func() O.Option[T.Tuple2[GU, U]], U any](data ...U) GU {
|
func From[GU ~func() O.Option[P.Pair[GU, U]], U any](data ...U) GU {
|
||||||
return FromArray[GU](data)
|
return FromArray[GU](data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty returns the empty iterator
|
// Empty returns the empty iterator
|
||||||
func Empty[GU ~func() O.Option[T.Tuple2[GU, U]], U any]() GU {
|
func Empty[GU ~func() O.Option[P.Pair[GU, U]], U any]() GU {
|
||||||
return IO.None[GU]()
|
return IO.None[GU]()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Of returns an iterator with one single element
|
// Of returns an iterator with one single element
|
||||||
func Of[GU ~func() O.Option[T.Tuple2[GU, U]], U any](a U) GU {
|
func Of[GU ~func() O.Option[P.Pair[GU, U]], U any](a U) GU {
|
||||||
return IO.Of[GU](T.MakeTuple2(Empty[GU](), a))
|
return IO.Of[GU](P.MakePair(Empty[GU](), a))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromArray returns an iterator from multiple elements
|
// FromArray returns an iterator from multiple elements
|
||||||
func FromArray[GU ~func() O.Option[T.Tuple2[GU, U]], US ~[]U, U any](as US) GU {
|
func FromArray[GU ~func() O.Option[P.Pair[GU, U]], US ~[]U, U any](as US) GU {
|
||||||
return A.MatchLeft(Empty[GU], func(head U, tail US) GU {
|
return A.MatchLeft(Empty[GU], func(head U, tail US) GU {
|
||||||
return func() O.Option[T.Tuple2[GU, U]] {
|
return func() O.Option[P.Pair[GU, U]] {
|
||||||
return O.Of(T.MakeTuple2(FromArray[GU](tail), head))
|
return O.Of(P.MakePair(FromArray[GU](tail), head))
|
||||||
}
|
}
|
||||||
})(as)
|
})(as)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reduce applies a function for each value of the iterator with a floating result
|
// reduce applies a function for each value of the iterator with a floating result
|
||||||
func reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](as GU, f func(V, U) V, initial V) V {
|
func reduce[GU ~func() O.Option[P.Pair[GU, U]], U, V any](as GU, f func(V, U) V, initial V) V {
|
||||||
next, ok := O.Unwrap(as())
|
next, ok := O.Unwrap(as())
|
||||||
current := initial
|
current := initial
|
||||||
for ok {
|
for ok {
|
||||||
@@ -74,18 +74,18 @@ func reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](as GU, f func(V, U)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reduce applies a function for each value of the iterator with a floating result
|
// Reduce applies a function for each value of the iterator with a floating result
|
||||||
func Reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](f func(V, U) V, initial V) func(GU) V {
|
func Reduce[GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(V, U) V, initial V) func(GU) V {
|
||||||
return F.Bind23of3(reduce[GU, U, V])(f, initial)
|
return F.Bind23of3(reduce[GU, U, V])(f, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToArray converts the iterator to an array
|
// ToArray converts the iterator to an array
|
||||||
func ToArray[GU ~func() O.Option[T.Tuple2[GU, U]], US ~[]U, U any](u GU) US {
|
func ToArray[GU ~func() O.Option[P.Pair[GU, U]], US ~[]U, U any](u GU) US {
|
||||||
return Reduce[GU](A.Append[US], A.Empty[US]())(u)
|
return Reduce[GU](A.Append[US], A.Empty[US]())(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) V, U, V any](f FCT) func(ma GU) GV {
|
func Map[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) V, U, V any](f FCT) func(ma GU) GV {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var m func(O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GV, V]]
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
||||||
|
|
||||||
recurse := func(ma GU) GV {
|
recurse := func(ma GU) GV {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -94,17 +94,17 @@ func Map[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
m = O.Map(T.Map2(recurse, f))
|
m = O.Map(P.BiMap(recurse, f))
|
||||||
|
|
||||||
return recurse
|
return recurse
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMap[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](ma GU, f func(U) V) GV {
|
func MonadMap[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) V) GV {
|
||||||
return Map[GV, GU](f)(ma)
|
return Map[GV, GU](f)(ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
func concat[GU ~func() O.Option[T.Tuple2[GU, U]], U any](right, left GU) GU {
|
func concat[GU ~func() O.Option[P.Pair[GU, U]], U any](right, left GU) GU {
|
||||||
var m func(ma O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GU, U]]
|
var m func(ma O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GU, U]]
|
||||||
|
|
||||||
recurse := func(left GU) GU {
|
recurse := func(left GU) GU {
|
||||||
return F.Nullary2(left, m)
|
return F.Nullary2(left, m)
|
||||||
@@ -113,16 +113,16 @@ func concat[GU ~func() O.Option[T.Tuple2[GU, U]], U any](right, left GU) GU {
|
|||||||
m = O.Fold(
|
m = O.Fold(
|
||||||
right,
|
right,
|
||||||
F.Flow2(
|
F.Flow2(
|
||||||
T.Map2(recurse, F.Identity[U]),
|
P.BiMap(recurse, F.Identity[U]),
|
||||||
O.Some[T.Tuple2[GU, U]],
|
O.Some[P.Pair[GU, U]],
|
||||||
))
|
))
|
||||||
|
|
||||||
return recurse(left)
|
return recurse(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chain[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](f func(U) GV) func(GU) GV {
|
func Chain[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(U) GV) func(GU) GV {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var m func(O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GV, V]]
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
||||||
|
|
||||||
recurse := func(ma GU) GV {
|
recurse := func(ma GU) GV {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -132,9 +132,9 @@ func Chain[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU
|
|||||||
}
|
}
|
||||||
m = O.Chain(
|
m = O.Chain(
|
||||||
F.Flow3(
|
F.Flow3(
|
||||||
T.Map2(recurse, f),
|
P.BiMap(recurse, f),
|
||||||
T.Tupled2(concat[GV]),
|
P.Paired(concat[GV]),
|
||||||
func(v GV) O.Option[T.Tuple2[GV, V]] {
|
func(v GV) O.Option[P.Pair[GV, V]] {
|
||||||
return v()
|
return v()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -143,11 +143,11 @@ func Chain[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU
|
|||||||
return recurse
|
return recurse
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChain[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](ma GU, f func(U) GV) GV {
|
func MonadChain[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) GV) GV {
|
||||||
return Chain[GV, GU](f)(ma)
|
return Chain[GV, GU](f)(ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainFirst[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](ma GU, f func(U) GV) GU {
|
func MonadChainFirst[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) GV) GU {
|
||||||
return C.MonadChainFirst(
|
return C.MonadChainFirst(
|
||||||
MonadChain[GU, GU, U, U],
|
MonadChain[GU, GU, U, U],
|
||||||
MonadMap[GU, GV, V, U],
|
MonadMap[GU, GV, V, U],
|
||||||
@@ -156,7 +156,7 @@ func MonadChainFirst[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChainFirst[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](f func(U) GV) func(GU) GU {
|
func ChainFirst[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(U) GV) func(GU) GU {
|
||||||
return C.ChainFirst(
|
return C.ChainFirst(
|
||||||
Chain[GU, GU, U, U],
|
Chain[GU, GU, U, U],
|
||||||
Map[GU, GV, func(V) U, V, U],
|
Map[GU, GV, func(V) U, V, U],
|
||||||
@@ -164,14 +164,14 @@ func ChainFirst[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tupl
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flatten[GV ~func() O.Option[T.Tuple2[GV, GU]], GU ~func() O.Option[T.Tuple2[GU, U]], U any](ma GV) GU {
|
func Flatten[GV ~func() O.Option[P.Pair[GV, GU]], GU ~func() O.Option[P.Pair[GU, U]], U any](ma GV) GU {
|
||||||
return MonadChain(ma, F.Identity[GU])
|
return MonadChain(ma, F.Identity[GU])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeBy returns an [Iterator] with an infinite number of elements initialized with `f(i)`
|
// MakeBy returns an [Iterator] with an infinite number of elements initialized with `f(i)`
|
||||||
func MakeBy[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(int) U, U any](f FCT) GU {
|
func MakeBy[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(int) U, U any](f FCT) GU {
|
||||||
|
|
||||||
var m func(int) O.Option[T.Tuple2[GU, U]]
|
var m func(int) O.Option[P.Pair[GU, U]]
|
||||||
|
|
||||||
recurse := func(i int) GU {
|
recurse := func(i int) GU {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -181,12 +181,12 @@ func MakeBy[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(int) U, U any](f FCT
|
|||||||
}
|
}
|
||||||
|
|
||||||
m = F.Flow3(
|
m = F.Flow3(
|
||||||
T.Replicate2[int],
|
P.Of[int],
|
||||||
T.Map2(F.Flow2(
|
P.BiMap(F.Flow2(
|
||||||
utils.Inc,
|
utils.Inc,
|
||||||
recurse),
|
recurse),
|
||||||
f),
|
f),
|
||||||
O.Of[T.Tuple2[GU, U]],
|
O.Of[P.Pair[GU, U]],
|
||||||
)
|
)
|
||||||
|
|
||||||
// bootstrap
|
// bootstrap
|
||||||
@@ -194,13 +194,13 @@ func MakeBy[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(int) U, U any](f FCT
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replicate creates an infinite [Iterator] containing a value.
|
// Replicate creates an infinite [Iterator] containing a value.
|
||||||
func Replicate[GU ~func() O.Option[T.Tuple2[GU, U]], U any](a U) GU {
|
func Replicate[GU ~func() O.Option[P.Pair[GU, U]], U any](a U) GU {
|
||||||
return MakeBy[GU](F.Constant1[int](a))
|
return MakeBy[GU](F.Constant1[int](a))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat creates an [Iterator] containing a value repeated the specified number of times.
|
// Repeat creates an [Iterator] containing a value repeated the specified number of times.
|
||||||
// Alias of [Replicate] combined with [Take]
|
// Alias of [Replicate] combined with [Take]
|
||||||
func Repeat[GU ~func() O.Option[T.Tuple2[GU, U]], U any](n int, a U) GU {
|
func Repeat[GU ~func() O.Option[P.Pair[GU, U]], U any](n int, a U) GU {
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
a,
|
a,
|
||||||
Replicate[GU],
|
Replicate[GU],
|
||||||
@@ -209,13 +209,13 @@ func Repeat[GU ~func() O.Option[T.Tuple2[GU, U]], U any](n int, a U) GU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Count creates an [Iterator] containing a consecutive sequence of integers starting with the provided start value
|
// Count creates an [Iterator] containing a consecutive sequence of integers starting with the provided start value
|
||||||
func Count[GU ~func() O.Option[T.Tuple2[GU, int]]](start int) GU {
|
func Count[GU ~func() O.Option[P.Pair[GU, int]]](start int) GU {
|
||||||
return MakeBy[GU](N.Add(start))
|
return MakeBy[GU](N.Add(start))
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterMap[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) O.Option[V], U, V any](f FCT) func(ma GU) GV {
|
func FilterMap[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) O.Option[V], U, V any](f FCT) func(ma GU) GV {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var m func(O.Option[T.Tuple2[GU, U]]) O.Option[T.Tuple2[GV, V]]
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
||||||
|
|
||||||
recurse := func(ma GU) GV {
|
recurse := func(ma GU) GV {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
@@ -226,11 +226,11 @@ func FilterMap[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple
|
|||||||
|
|
||||||
m = O.Fold(
|
m = O.Fold(
|
||||||
Empty[GV](),
|
Empty[GV](),
|
||||||
func(t T.Tuple2[GU, U]) O.Option[T.Tuple2[GV, V]] {
|
func(t P.Pair[GU, U]) O.Option[P.Pair[GV, V]] {
|
||||||
r := recurse(Next(t))
|
r := recurse(Next(t))
|
||||||
return O.MonadFold(f(Current(t)), r, F.Flow2(
|
return O.MonadFold(f(Current(t)), r, F.Flow2(
|
||||||
F.Bind1st(T.MakeTuple2[GV, V], r),
|
F.Bind1st(P.MakePair[GV, V], r),
|
||||||
O.Some[T.Tuple2[GV, V]],
|
O.Some[P.Pair[GV, V]],
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -238,26 +238,26 @@ func FilterMap[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple
|
|||||||
return recurse
|
return recurse
|
||||||
}
|
}
|
||||||
|
|
||||||
func Filter[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) bool, U any](f FCT) func(ma GU) GU {
|
func Filter[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) bool, U any](f FCT) func(ma GU) GU {
|
||||||
return FilterMap[GU, GU](O.FromPredicate(f))
|
return FilterMap[GU, GU](O.FromPredicate(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ap[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](ma GU) func(fab GUV) GV {
|
func Ap[GUV ~func() O.Option[P.Pair[GUV, func(U) V]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU) func(fab GUV) GV {
|
||||||
return Chain[GV, GUV](F.Bind1st(MonadMap[GV, GU], ma))
|
return Chain[GV, GUV](F.Bind1st(MonadMap[GV, GU], ma))
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](fab GUV, ma GU) GV {
|
func MonadAp[GUV ~func() O.Option[P.Pair[GUV, func(U) V]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](fab GUV, ma GU) GV {
|
||||||
return Ap[GUV, GV, GU](ma)(fab)
|
return Ap[GUV, GV, GU](ma)(fab)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterChain[GVV ~func() O.Option[T.Tuple2[GVV, GV]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) O.Option[GV], U, V any](f FCT) func(ma GU) GV {
|
func FilterChain[GVV ~func() O.Option[P.Pair[GVV, GV]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) O.Option[GV], U, V any](f FCT) func(ma GU) GV {
|
||||||
return F.Flow2(
|
return F.Flow2(
|
||||||
FilterMap[GVV, GU](f),
|
FilterMap[GVV, GU](f),
|
||||||
Flatten[GVV],
|
Flatten[GVV],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FoldMap[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) V, U, V any](m M.Monoid[V]) func(FCT) func(ma GU) V {
|
func FoldMap[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) V, U, V any](m M.Monoid[V]) func(FCT) func(ma GU) V {
|
||||||
return func(f FCT) func(ma GU) V {
|
return func(f FCT) func(ma GU) V {
|
||||||
return Reduce[GU](func(cur V, a U) V {
|
return Reduce[GU](func(cur V, a U) V {
|
||||||
return m.Concat(cur, f(a))
|
return m.Concat(cur, f(a))
|
||||||
@@ -265,6 +265,6 @@ func FoldMap[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) V, U, V any](m M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fold[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m M.Monoid[U]) func(ma GU) U {
|
func Fold[GU ~func() O.Option[P.Pair[GU, U]], U any](m M.Monoid[U]) func(ma GU) U {
|
||||||
return Reduce[GU](m.Concat, m.Empty())
|
return Reduce[GU](m.Concat, m.Empty())
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,10 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Last returns the last item in an iterator if such an item exists
|
// Last returns the last item in an iterator if such an item exists
|
||||||
func Last[GU ~func() O.Option[T.Tuple2[GU, U]], U any](mu GU) O.Option[U] {
|
func Last[GU ~func() O.Option[P.Pair[GU, U]], U any](mu GU) O.Option[U] {
|
||||||
return reduce(mu, F.Ignore1of2[O.Option[U]](O.Of[U]), O.None[U]())
|
return reduce(mu, F.Ignore1of2[O.Option[U]](O.Of[U]), O.None[U]())
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,10 @@ package generic
|
|||||||
import (
|
import (
|
||||||
"github.com/IBM/fp-go/internal/monad"
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
type iteratorMonad[A, B any, GA ~func() O.Option[T.Tuple2[GA, A]], GB ~func() O.Option[T.Tuple2[GB, B]], GAB ~func() O.Option[T.Tuple2[GAB, func(A) B]]] struct{}
|
type iteratorMonad[A, B any, GA ~func() O.Option[P.Pair[GA, A]], GB ~func() O.Option[P.Pair[GB, B]], GAB ~func() O.Option[P.Pair[GAB, func(A) B]]] struct{}
|
||||||
|
|
||||||
func (o *iteratorMonad[A, B, GA, GB, GAB]) Of(a A) GA {
|
func (o *iteratorMonad[A, B, GA, GB, GAB]) Of(a A) GA {
|
||||||
return Of[GA, A](a)
|
return Of[GA, A](a)
|
||||||
@@ -40,6 +40,6 @@ func (o *iteratorMonad[A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Monad implements the monadic operations for iterators
|
// Monad implements the monadic operations for iterators
|
||||||
func Monad[A, B any, GA ~func() O.Option[T.Tuple2[GA, A]], GB ~func() O.Option[T.Tuple2[GB, B]], GAB ~func() O.Option[T.Tuple2[GAB, func(A) B]]]() monad.Monad[A, B, GA, GB, GAB] {
|
func Monad[A, B any, GA ~func() O.Option[P.Pair[GA, A]], GB ~func() O.Option[P.Pair[GB, B]], GAB ~func() O.Option[P.Pair[GAB, func(A) B]]]() monad.Monad[A, B, GA, GB, GAB] {
|
||||||
return &iteratorMonad[A, B, GA, GB, GAB]{}
|
return &iteratorMonad[A, B, GA, GB, GAB]{}
|
||||||
}
|
}
|
||||||
|
@@ -19,10 +19,10 @@ import (
|
|||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Monoid[GU ~func() O.Option[T.Tuple2[GU, U]], U any]() M.Monoid[GU] {
|
func Monoid[GU ~func() O.Option[P.Pair[GU, U]], U any]() M.Monoid[GU] {
|
||||||
return M.MakeMonoid(
|
return M.MakeMonoid(
|
||||||
F.Swap(concat[GU]),
|
F.Swap(concat[GU]),
|
||||||
Empty[GU](),
|
Empty[GU](),
|
||||||
|
@@ -24,10 +24,10 @@ import (
|
|||||||
N "github.com/IBM/fp-go/number"
|
N "github.com/IBM/fp-go/number"
|
||||||
I "github.com/IBM/fp-go/number/integer"
|
I "github.com/IBM/fp-go/number/integer"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
func FromReflect[GR ~func() O.Option[T.Tuple2[GR, R.Value]]](val R.Value) GR {
|
func FromReflect[GR ~func() O.Option[P.Pair[GR, R.Value]]](val R.Value) GR {
|
||||||
// recursive callback
|
// recursive callback
|
||||||
var recurse func(idx int) GR
|
var recurse func(idx int) GR
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ func FromReflect[GR ~func() O.Option[T.Tuple2[GR, R.Value]]](val R.Value) GR {
|
|||||||
L.Map(fromPred),
|
L.Map(fromPred),
|
||||||
LG.Map[L.Lazy[O.Option[int]], GR](O.Map(
|
LG.Map[L.Lazy[O.Option[int]], GR](O.Map(
|
||||||
F.Flow2(
|
F.Flow2(
|
||||||
T.Replicate2[int],
|
P.Of[int],
|
||||||
T.Map2(F.Flow2(N.Add(1), recurse), val.Index),
|
P.BiMap(F.Flow2(N.Add(1), recurse), val.Index),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
@@ -18,14 +18,14 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apTuple[A, B any](t T.Tuple2[func(A) B, A]) T.Tuple2[B, A] {
|
func apTuple[A, B any](t P.Pair[func(A) B, A]) P.Pair[B, A] {
|
||||||
return T.MakeTuple2(t.F1(t.F2), t.F2)
|
return P.MakePair(P.Head(t)(P.Tail(t)), P.Tail(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Scan[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(V, U) V, U, V any](f FCT, initial V) func(ma GU) GV {
|
func Scan[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(V, U) V, U, V any](f FCT, initial V) func(ma GU) GV {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var m func(GU) func(V) GV
|
var m func(GU) func(V) GV
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ func Scan[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU,
|
|||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
ma,
|
ma,
|
||||||
O.Map(F.Flow2(
|
O.Map(F.Flow2(
|
||||||
T.Map2(m, F.Bind1st(f, current)),
|
P.BiMap(m, F.Bind1st(f, current)),
|
||||||
apTuple[V, GV],
|
apTuple[V, GV],
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
@@ -19,10 +19,10 @@ import (
|
|||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
N "github.com/IBM/fp-go/number/integer"
|
N "github.com/IBM/fp-go/number/integer"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Take[GU ~func() O.Option[T.Tuple2[GU, U]], U any](n int) func(ma GU) GU {
|
func Take[GU ~func() O.Option[P.Pair[GU, U]], U any](n int) func(ma GU) GU {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var recurse func(ma GU, idx int) GU
|
var recurse func(ma GU, idx int) GU
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ func Take[GU ~func() O.Option[T.Tuple2[GU, U]], U any](n int) func(ma GU) GU {
|
|||||||
fromPred,
|
fromPred,
|
||||||
O.Chain(F.Ignore1of1[int](F.Nullary2(
|
O.Chain(F.Ignore1of1[int](F.Nullary2(
|
||||||
ma,
|
ma,
|
||||||
O.Map(T.Map2(F.Bind2nd(recurse, idx+1), F.Identity[U])),
|
O.Map(P.BiMap(F.Bind2nd(recurse, idx+1), F.Identity[U])),
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// addToMap makes a deep copy of a map and adds a value
|
// addToMap makes a deep copy of a map and adds a value
|
||||||
@@ -31,23 +31,23 @@ func addToMap[A comparable](a A, m map[A]bool) map[A]bool {
|
|||||||
return cpy
|
return cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uniq[AS ~func() O.Option[T.Tuple2[AS, A]], K comparable, A any](f func(A) K) func(as AS) AS {
|
func Uniq[AS ~func() O.Option[P.Pair[AS, A]], K comparable, A any](f func(A) K) func(as AS) AS {
|
||||||
|
|
||||||
var recurse func(as AS, mp map[K]bool) AS
|
var recurse func(as AS, mp map[K]bool) AS
|
||||||
|
|
||||||
recurse = func(as AS, mp map[K]bool) AS {
|
recurse = func(as AS, mp map[K]bool) AS {
|
||||||
return F.Nullary2(
|
return F.Nullary2(
|
||||||
as,
|
as,
|
||||||
O.Chain(func(a T.Tuple2[AS, A]) O.Option[T.Tuple2[AS, A]] {
|
O.Chain(func(a P.Pair[AS, A]) O.Option[P.Pair[AS, A]] {
|
||||||
return F.Pipe3(
|
return F.Pipe3(
|
||||||
a.F2,
|
P.Tail(a),
|
||||||
f,
|
f,
|
||||||
O.FromPredicate(func(k K) bool {
|
O.FromPredicate(func(k K) bool {
|
||||||
_, ok := mp[k]
|
_, ok := mp[k]
|
||||||
return !ok
|
return !ok
|
||||||
}),
|
}),
|
||||||
O.Fold(recurse(a.F1, mp), func(k K) O.Option[T.Tuple2[AS, A]] {
|
O.Fold(recurse(P.Head(a), mp), func(k K) O.Option[P.Pair[AS, A]] {
|
||||||
return O.Of(T.MakeTuple2(recurse(a.F1, addToMap(k, mp)), a.F2))
|
return O.Of(P.MakePair(recurse(P.Head(a), addToMap(k, mp)), P.Tail(a)))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@@ -57,6 +57,6 @@ func Uniq[AS ~func() O.Option[T.Tuple2[AS, A]], K comparable, A any](f func(A) K
|
|||||||
return F.Bind2nd(recurse, make(map[K]bool, 0))
|
return F.Bind2nd(recurse, make(map[K]bool, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func StrictUniq[AS ~func() O.Option[T.Tuple2[AS, A]], A comparable](as AS) AS {
|
func StrictUniq[AS ~func() O.Option[P.Pair[AS, A]], A comparable](as AS) AS {
|
||||||
return Uniq[AS](F.Identity[A])(as)
|
return Uniq[AS](F.Identity[A])(as)
|
||||||
}
|
}
|
||||||
|
@@ -18,29 +18,29 @@ package generic
|
|||||||
import (
|
import (
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ZipWith applies a function to pairs of elements at the same index in two iterators, collecting the results in a new iterator. If one
|
// ZipWith applies a function to pairs of elements at the same index in two iterators, collecting the results in a new iterator. If one
|
||||||
// input iterator is short, excess elements of the longer iterator are discarded.
|
// input iterator is short, excess elements of the longer iterator are discarded.
|
||||||
func ZipWith[AS ~func() O.Option[T.Tuple2[AS, A]], BS ~func() O.Option[T.Tuple2[BS, B]], CS ~func() O.Option[T.Tuple2[CS, C]], FCT ~func(A, B) C, A, B, C any](fa AS, fb BS, f FCT) CS {
|
func ZipWith[AS ~func() O.Option[P.Pair[AS, A]], BS ~func() O.Option[P.Pair[BS, B]], CS ~func() O.Option[P.Pair[CS, C]], FCT ~func(A, B) C, A, B, C any](fa AS, fb BS, f FCT) CS {
|
||||||
// pre-declare to avoid cyclic reference
|
// pre-declare to avoid cyclic reference
|
||||||
var m func(T.Tuple2[O.Option[T.Tuple2[AS, A]], O.Option[T.Tuple2[BS, B]]]) O.Option[T.Tuple2[CS, C]]
|
var m func(P.Pair[O.Option[P.Pair[AS, A]], O.Option[P.Pair[BS, B]]]) O.Option[P.Pair[CS, C]]
|
||||||
|
|
||||||
recurse := func(as AS, bs BS) CS {
|
recurse := func(as AS, bs BS) CS {
|
||||||
return func() O.Option[T.Tuple2[CS, C]] {
|
return func() O.Option[P.Pair[CS, C]] {
|
||||||
// combine
|
// combine
|
||||||
return F.Pipe1(
|
return F.Pipe1(
|
||||||
T.MakeTuple2(as(), bs()),
|
P.MakePair(as(), bs()),
|
||||||
m,
|
m,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m = F.Flow2(
|
m = F.Flow2(
|
||||||
O.SequenceTuple2[T.Tuple2[AS, A], T.Tuple2[BS, B]],
|
O.SequencePair[P.Pair[AS, A], P.Pair[BS, B]],
|
||||||
O.Map(func(t T.Tuple2[T.Tuple2[AS, A], T.Tuple2[BS, B]]) T.Tuple2[CS, C] {
|
O.Map(func(t P.Pair[P.Pair[AS, A], P.Pair[BS, B]]) P.Pair[CS, C] {
|
||||||
return T.MakeTuple2(recurse(t.F1.F1, t.F2.F1), f(t.F1.F2, t.F2.F2))
|
return P.MakePair(recurse(P.Head(P.Head(t)), P.Head(P.Tail(t))), f(P.Tail(P.Head(t)), P.Tail(P.Tail(t))))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// trigger the recursion
|
// trigger the recursion
|
||||||
@@ -49,6 +49,6 @@ func ZipWith[AS ~func() O.Option[T.Tuple2[AS, A]], BS ~func() O.Option[T.Tuple2[
|
|||||||
|
|
||||||
// Zip takes two iterators and returns an iterators of corresponding pairs. If one input iterators is short, excess elements of the
|
// Zip takes two iterators and returns an iterators of corresponding pairs. If one input iterators is short, excess elements of the
|
||||||
// longer iterator are discarded
|
// longer iterator are discarded
|
||||||
func Zip[AS ~func() O.Option[T.Tuple2[AS, A]], BS ~func() O.Option[T.Tuple2[BS, B]], CS ~func() O.Option[T.Tuple2[CS, T.Tuple2[A, B]]], A, B any](fb BS) func(AS) CS {
|
func Zip[AS ~func() O.Option[P.Pair[AS, A]], BS ~func() O.Option[P.Pair[BS, B]], CS ~func() O.Option[P.Pair[CS, P.Pair[A, B]]], A, B any](fb BS) func(AS) CS {
|
||||||
return F.Bind23of3(ZipWith[AS, BS, CS, func(A, B) T.Tuple2[A, B]])(fb, T.MakeTuple2[A, B])
|
return F.Bind23of3(ZipWith[AS, BS, CS, func(A, B) P.Pair[A, B]])(fb, P.MakePair[A, B])
|
||||||
}
|
}
|
||||||
|
@@ -20,19 +20,19 @@ import (
|
|||||||
L "github.com/IBM/fp-go/lazy"
|
L "github.com/IBM/fp-go/lazy"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Iterator represents a stateless, pure way to iterate over a sequence
|
// Iterator represents a stateless, pure way to iterate over a sequence
|
||||||
type Iterator[U any] L.Lazy[O.Option[T.Tuple2[Iterator[U], U]]]
|
type Iterator[U any] L.Lazy[O.Option[P.Pair[Iterator[U], U]]]
|
||||||
|
|
||||||
// Next returns the [Iterator] for the next element in an iterator `T.Tuple2`
|
// Next returns the [Iterator] for the next element in an iterator `P.Pair`
|
||||||
func Next[U any](m T.Tuple2[Iterator[U], U]) Iterator[U] {
|
func Next[U any](m P.Pair[Iterator[U], U]) Iterator[U] {
|
||||||
return G.Next(m)
|
return G.Next(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current returns the current element in an [Iterator] `T.Tuple2`
|
// Current returns the current element in an [Iterator] `P.Pair`
|
||||||
func Current[U any](m T.Tuple2[Iterator[U], U]) U {
|
func Current[U any](m P.Pair[Iterator[U], U]) U {
|
||||||
return G.Current(m)
|
return G.Current(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,14 +29,14 @@ func TestScan(t *testing.T) {
|
|||||||
|
|
||||||
dst := F.Pipe1(
|
dst := F.Pipe1(
|
||||||
src,
|
src,
|
||||||
Scan(func(cur T.Tuple2[int, string], val string) T.Tuple2[int, string] {
|
Scan(func(cur P.Pair[int, string], val string) P.Pair[int, string] {
|
||||||
return T.MakeTuple2(cur.F1+1, val)
|
return P.MakePair(P.Head(cur)+1, val)
|
||||||
}, T.MakeTuple2(0, "")),
|
}, P.MakePair(0, "")),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.Equal(t, ToArray(From(
|
assert.Equal(t, ToArray(From(
|
||||||
T.MakeTuple2(1, "a"),
|
P.MakePair(1, "a"),
|
||||||
T.MakeTuple2(2, "b"),
|
P.MakePair(2, "b"),
|
||||||
T.MakeTuple2(3, "c"),
|
P.MakePair(3, "c"),
|
||||||
)), ToArray(dst))
|
)), ToArray(dst))
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ package stateless
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ZipWith applies a function to pairs of elements at the same index in two iterators, collecting the results in a new iterator. If one
|
// ZipWith applies a function to pairs of elements at the same index in two iterators, collecting the results in a new iterator. If one
|
||||||
@@ -28,6 +28,6 @@ func ZipWith[FCT ~func(A, B) C, A, B, C any](fa Iterator[A], fb Iterator[B], f F
|
|||||||
|
|
||||||
// Zip takes two iterators and returns an iterators of corresponding pairs. If one input iterators is short, excess elements of the
|
// Zip takes two iterators and returns an iterators of corresponding pairs. If one input iterators is short, excess elements of the
|
||||||
// longer iterator are discarded
|
// longer iterator are discarded
|
||||||
func Zip[A, B any](fb Iterator[B]) func(Iterator[A]) Iterator[T.Tuple2[A, B]] {
|
func Zip[A, B any](fb Iterator[B]) func(Iterator[A]) Iterator[P.Pair[A, B]] {
|
||||||
return G.Zip[Iterator[A], Iterator[B], Iterator[T.Tuple2[A, B]]](fb)
|
return G.Zip[Iterator[A], Iterator[B], Iterator[P.Pair[A, B]]](fb)
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
P "github.com/IBM/fp-go/pair"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,5 +40,5 @@ func TestZip(t *testing.T) {
|
|||||||
|
|
||||||
res := Zip[string](left)(right)
|
res := Zip[string](left)(right)
|
||||||
|
|
||||||
assert.Equal(t, ToArray(From(T.MakeTuple2("a", 1), T.MakeTuple2("b", 2), T.MakeTuple2("c", 3))), ToArray(res))
|
assert.Equal(t, ToArray(From(P.MakePair("a", 1), P.MakePair("b", 2), P.MakePair("c", 3))), ToArray(res))
|
||||||
}
|
}
|
||||||
|
30
option/pair.go
Normal file
30
option/pair.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (c) 2024 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 option
|
||||||
|
|
||||||
|
import (
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
PG "github.com/IBM/fp-go/pair/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SequencePair converts a [Pair] of [Option[T]] into an [Option[Pair]].
|
||||||
|
func SequencePair[T1, T2 any](t P.Pair[Option[T1], Option[T2]]) Option[P.Pair[T1, T2]] {
|
||||||
|
return PG.SequencePair(
|
||||||
|
Map[T1, func(T2) P.Pair[T1, T2]],
|
||||||
|
Ap[P.Pair[T1, T2], T2],
|
||||||
|
t,
|
||||||
|
)
|
||||||
|
}
|
71
pair/generic/sequence.go
Normal file
71
pair/generic/sequence.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SequencePair is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||||
|
// The function takes a [Pair] of higher higher kinded types and returns a higher kinded type of a [Pair] with the resolved values.
|
||||||
|
func SequencePair[
|
||||||
|
MAP ~func(func(T1) func(T2) P.Pair[T1, T2]) func(HKT_T1) HKT_F_T2,
|
||||||
|
AP1 ~func(HKT_T2) func(HKT_F_T2) HKT_PAIR,
|
||||||
|
T1,
|
||||||
|
T2,
|
||||||
|
HKT_T1, // HKT[T1]
|
||||||
|
HKT_T2, // HKT[T2]
|
||||||
|
HKT_F_T2, // HKT[func(T2) P.Pair[T1, T2]]
|
||||||
|
HKT_PAIR any, // HKT[Pair[T1, T2]]
|
||||||
|
](
|
||||||
|
fmap MAP,
|
||||||
|
fap1 AP1,
|
||||||
|
t P.Pair[HKT_T1, HKT_T2],
|
||||||
|
) HKT_PAIR {
|
||||||
|
return F.Pipe2(
|
||||||
|
P.Head(t),
|
||||||
|
fmap(F.Curry2(P.MakePair[T1, T2])),
|
||||||
|
fap1(P.Tail(t)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraversePair is a utility function used to implement the sequence operation for higher kinded types based only on map and ap.
|
||||||
|
// The function takes a [Pair] of base types and 2 functions that transform these based types into higher higher kinded types. It returns a higher kinded type of a [Pair] with the resolved values.
|
||||||
|
func TraversePair[
|
||||||
|
MAP ~func(func(T1) func(T2) P.Pair[T1, T2]) func(HKT_T1) HKT_F_T2,
|
||||||
|
AP1 ~func(HKT_T2) func(HKT_F_T2) HKT_PAIR,
|
||||||
|
F1 ~func(A1) HKT_T1,
|
||||||
|
F2 ~func(A2) HKT_T2,
|
||||||
|
A1, T1,
|
||||||
|
A2, T2,
|
||||||
|
HKT_T1, // HKT[T1]
|
||||||
|
HKT_T2, // HKT[T2]
|
||||||
|
HKT_F_T2, // HKT[func(T2) P.Pair[T1, T2]]
|
||||||
|
HKT_PAIR any, // HKT[Pair[T1, T2]]
|
||||||
|
](
|
||||||
|
fmap MAP,
|
||||||
|
fap1 AP1,
|
||||||
|
f1 F1,
|
||||||
|
f2 F2,
|
||||||
|
t P.Pair[A1, A2],
|
||||||
|
) HKT_PAIR {
|
||||||
|
return F.Pipe2(
|
||||||
|
f1(P.Head(t)),
|
||||||
|
fmap(F.Curry2(P.MakePair[T1, T2])),
|
||||||
|
fap1(f2(P.Tail(t))),
|
||||||
|
)
|
||||||
|
}
|
49
pair/pair.go
49
pair/pair.go
@@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
pair struct {
|
pair struct {
|
||||||
head, Tail any
|
h, t any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pair defines a data structure that holds two strongly typed values
|
// Pair defines a data structure that holds two strongly typed values
|
||||||
@@ -36,7 +36,7 @@ type (
|
|||||||
//
|
//
|
||||||
// go:noinline
|
// go:noinline
|
||||||
func pairString(s *pair) string {
|
func pairString(s *pair) string {
|
||||||
return fmt.Sprintf("Pair[%T, %t](%v, %v)", s.head, s.Tail, s.head, s.Tail)
|
return fmt.Sprintf("Pair[%T, %t](%v, %v)", s.h, s.t, s.h, s.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format prints some debug info for the object
|
// Format prints some debug info for the object
|
||||||
@@ -63,12 +63,12 @@ func (s Pair[A, B]) Format(f fmt.State, c rune) {
|
|||||||
|
|
||||||
// Of creates a [Pair] with the same value to to both fields
|
// Of creates a [Pair] with the same value to to both fields
|
||||||
func Of[A any](value A) Pair[A, A] {
|
func Of[A any](value A) Pair[A, A] {
|
||||||
return Pair[A, A]{head: value, Tail: value}
|
return Pair[A, A]{h: value, t: value}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromTuple creates a [Pair] from a [T.Tuple2]
|
// FromTuple creates a [Pair] from a [T.Tuple2]
|
||||||
func FromTuple[A, B any](t T.Tuple2[A, B]) Pair[A, B] {
|
func FromTuple[A, B any](t T.Tuple2[A, B]) Pair[A, B] {
|
||||||
return Pair[A, B]{head: t.F1, Tail: t.F2}
|
return Pair[A, B]{h: t.F1, t: t.F2}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTuple creates a [T.Tuple2] from a [Pair]
|
// ToTuple creates a [T.Tuple2] from a [Pair]
|
||||||
@@ -78,22 +78,22 @@ func ToTuple[A, B any](t Pair[A, B]) T.Tuple2[A, B] {
|
|||||||
|
|
||||||
// MakePair creates a [Pair] from two values
|
// MakePair creates a [Pair] from two values
|
||||||
func MakePair[A, B any](a A, b B) Pair[A, B] {
|
func MakePair[A, B any](a A, b B) Pair[A, B] {
|
||||||
return Pair[A, B]{head: a, Tail: b}
|
return Pair[A, B]{h: a, t: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Head returns the head value of the pair
|
// Head returns the head value of the pair
|
||||||
func Head[A, B any](fa Pair[A, B]) A {
|
func Head[A, B any](fa Pair[A, B]) A {
|
||||||
return fa.head.(A)
|
return fa.h.(A)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tail returns the head value of the pair
|
// Tail returns the head value of the pair
|
||||||
func Tail[A, B any](fa Pair[A, B]) B {
|
func Tail[A, B any](fa Pair[A, B]) B {
|
||||||
return fa.Tail.(B)
|
return fa.t.(B)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadMapHead maps the head value
|
// MonadMapHead maps the head value
|
||||||
func MonadMapHead[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B] {
|
func MonadMapHead[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B] {
|
||||||
return Pair[A1, B]{f(Head(fa)), fa.Tail}
|
return Pair[A1, B]{f(Head(fa)), fa.t}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadMap maps the head value
|
// MonadMap maps the head value
|
||||||
@@ -103,7 +103,7 @@ func MonadMap[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B] {
|
|||||||
|
|
||||||
// MonadMapTail maps the Tail value
|
// MonadMapTail maps the Tail value
|
||||||
func MonadMapTail[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1] {
|
func MonadMapTail[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1] {
|
||||||
return Pair[A, B1]{fa.head, f(Tail(fa))}
|
return Pair[A, B1]{fa.h, f(Tail(fa))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadBiMap maps both values
|
// MonadBiMap maps both values
|
||||||
@@ -136,13 +136,13 @@ func BiMap[A, B, A1, B1 any](f func(A) A1, g func(B) B1) func(Pair[A, B]) Pair[A
|
|||||||
// MonadChainHead chains on the head value
|
// MonadChainHead chains on the head value
|
||||||
func MonadChainHead[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B] {
|
func MonadChainHead[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B] {
|
||||||
fb := f(Head(fa))
|
fb := f(Head(fa))
|
||||||
return Pair[A1, B]{fb.head, sg.Concat(Tail(fa), Tail(fb))}
|
return Pair[A1, B]{fb.h, sg.Concat(Tail(fa), Tail(fb))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadChainTail chains on the Tail value
|
// MonadChainTail chains on the Tail value
|
||||||
func MonadChainTail[A, B, B1 any](sg Sg.Semigroup[A], fb Pair[A, B], f func(B) Pair[A, B1]) Pair[A, B1] {
|
func MonadChainTail[A, B, B1 any](sg Sg.Semigroup[A], fb Pair[A, B], f func(B) Pair[A, B1]) Pair[A, B1] {
|
||||||
fa := f(Tail(fb))
|
fa := f(Tail(fb))
|
||||||
return Pair[A, B1]{sg.Concat(Head(fb), Head(fa)), fa.Tail}
|
return Pair[A, B1]{sg.Concat(Head(fb), Head(fa)), fa.t}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadChain chains on the head value
|
// MonadChain chains on the head value
|
||||||
@@ -202,3 +202,30 @@ func ApTail[A, B, B1 any](sg Sg.Semigroup[A], fb Pair[A, B]) func(Pair[A, func(B
|
|||||||
func Ap[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B] {
|
func Ap[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B] {
|
||||||
return ApHead[B, A, A1](sg, fa)
|
return ApHead[B, A, A1](sg, fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Swap swaps the two channels
|
||||||
|
func Swap[A, B any](fa Pair[A, B]) Pair[B, A] {
|
||||||
|
return MakePair(Tail(fa), Head(fa))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paired converts a function with 2 parameters into a function taking a [Pair]
|
||||||
|
// The inverse function is [Unpaired]
|
||||||
|
func Paired[F ~func(T1, T2) R, T1, T2, R any](f F) func(Pair[T1, T2]) R {
|
||||||
|
return func(t Pair[T1, T2]) R {
|
||||||
|
return f(Head(t), Tail(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpaired converts a function with a [Pair] parameter into a function with 2 parameters
|
||||||
|
// The inverse function is [Paired]
|
||||||
|
func Unpaired[F ~func(Pair[T1, T2]) R, T1, T2, R any](f F) func(T1, T2) R {
|
||||||
|
return func(t1 T1, t2 T2) R {
|
||||||
|
return f(MakePair(t1, t2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Merge[F ~func(B) func(A) R, A, B, R any](f F) func(Pair[A, B]) R {
|
||||||
|
return func(p Pair[A, B]) R {
|
||||||
|
return f(Tail(p))(Head(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
scan.bat
Normal file
3
scan.bat
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
busybox find . -type f -name "*\.go" | busybox xargs gopls check
|
31
state/eq.go
Normal file
31
state/eq.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
G "github.com/IBM/fp-go/state/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constructs an equal predicate for a [State]
|
||||||
|
func Eq[S, A any](w EQ.Eq[S], a EQ.Eq[A]) func(S) EQ.Eq[State[S, A]] {
|
||||||
|
return G.Eq[State[S, A]](w, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||||
|
func FromStrictEquals[S, A comparable]() func(S) EQ.Eq[State[S, A]] {
|
||||||
|
return G.FromStrictEquals[State[S, A]]()
|
||||||
|
}
|
36
state/generic/eq.go
Normal file
36
state/generic/eq.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constructs an equal predicate for a [State]
|
||||||
|
func Eq[GA ~func(S) P.Pair[A, S], S, A any](w EQ.Eq[S], a EQ.Eq[A]) func(S) EQ.Eq[GA] {
|
||||||
|
eqp := P.Eq(a, w)
|
||||||
|
return func(s S) EQ.Eq[GA] {
|
||||||
|
return EQ.FromEquals(func(l, r GA) bool {
|
||||||
|
return eqp.Equals(l(s), r(s))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||||
|
func FromStrictEquals[GA ~func(S) P.Pair[A, S], S, A comparable]() func(S) EQ.Eq[GA] {
|
||||||
|
return Eq[GA](EQ.FromStrictEquals[S](), EQ.FromStrictEquals[A]())
|
||||||
|
}
|
88
state/generic/monad.go
Normal file
88
state/generic/monad.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
type statePointed[GA ~func(S) P.Pair[A, S], S, A any] struct{}
|
||||||
|
|
||||||
|
type stateFunctor[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
|
||||||
|
|
||||||
|
type stateApplicative[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
|
||||||
|
|
||||||
|
type stateMonad[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
|
||||||
|
|
||||||
|
func (o *statePointed[GA, S, A]) Of(a A) GA {
|
||||||
|
return Of[GA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Of(a A) GA {
|
||||||
|
return Of[GA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateMonad[GB, GAB, GA, S, A, B]) Of(a A) GA {
|
||||||
|
return Of[GA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateFunctor[GB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateMonad[GB, GAB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateMonad[GB, GAB, GA, S, A, B]) Chain(f func(A) GB) func(GA) GB {
|
||||||
|
return Chain[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Ap(fa GA) func(GAB) GB {
|
||||||
|
return Ap[GB, GAB, GA](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateMonad[GB, GAB, GA, S, A, B]) Ap(fa GA) func(GAB) GB {
|
||||||
|
return Ap[GB, GAB, GA](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [Writer]
|
||||||
|
func Pointed[GA ~func(S) P.Pair[A, S], S, A any]() pointed.Pointed[A, GA] {
|
||||||
|
return &statePointed[GA, S, A]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor implements the functor operations for [Writer]
|
||||||
|
func Functor[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() functor.Functor[A, B, GA, GB] {
|
||||||
|
return &stateFunctor[GB, GA, S, A, B]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative implements the applicative operations for [Writer]
|
||||||
|
func Applicative[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() applicative.Applicative[A, B, GA, GB, GAB] {
|
||||||
|
return &stateApplicative[GB, GAB, GA, S, A, B]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [Writer]
|
||||||
|
func Monad[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() monad.Monad[A, B, GA, GB, GAB] {
|
||||||
|
return &stateMonad[GB, GAB, GA, S, A, B]{}
|
||||||
|
}
|
131
state/generic/state.go
Normal file
131
state/generic/state.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
C "github.com/IBM/fp-go/internal/chain"
|
||||||
|
FC "github.com/IBM/fp-go/internal/functor"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
undefined any = struct{}{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func Get[GA ~func(S) P.Pair[S, S], S any]() GA {
|
||||||
|
return P.Of[S]
|
||||||
|
}
|
||||||
|
|
||||||
|
func Gets[GA ~func(S) P.Pair[A, S], FCT ~func(S) A, A, S any](f FCT) GA {
|
||||||
|
return func(s S) P.Pair[A, S] {
|
||||||
|
return P.MakePair(f(s), s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Put[GA ~func(S) P.Pair[any, S], S any]() GA {
|
||||||
|
return F.Bind1st(P.MakePair[any, S], undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Modify[GA ~func(S) P.Pair[any, S], FCT ~func(S) S, S any](f FCT) GA {
|
||||||
|
return F.Flow2(
|
||||||
|
f,
|
||||||
|
F.Bind1st(P.MakePair[any, S], undefined),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Of[GA ~func(S) P.Pair[A, S], S, A any](a A) GA {
|
||||||
|
return F.Bind1st(P.MakePair[A, S], a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMap[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) B, S, A, B any](fa GA, f FCT) GB {
|
||||||
|
return func(s S) P.Pair[B, S] {
|
||||||
|
p2 := fa(s)
|
||||||
|
return P.MakePair(f(P.Head(p2)), P.Tail(p2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) B, S, A, B any](f FCT) func(GA) GB {
|
||||||
|
return F.Bind2nd(MonadMap[GB, GA, FCT, S, A, B], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](fa GA, f FCT) GB {
|
||||||
|
return func(s S) P.Pair[B, S] {
|
||||||
|
a := fa(s)
|
||||||
|
return f(P.Head(a))(P.Tail(a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](f FCT) func(GA) GB {
|
||||||
|
return F.Bind2nd(MonadChain[GB, GA, FCT, S, A, B], f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadAp[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any](fab GAB, fa GA) GB {
|
||||||
|
return func(s S) P.Pair[B, S] {
|
||||||
|
f := fab(s)
|
||||||
|
a := fa(P.Tail(f))
|
||||||
|
|
||||||
|
return P.MakePair(P.Head(f)(P.Head(a)), P.Tail(a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ap[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any](ga GA) func(GAB) GB {
|
||||||
|
return F.Bind2nd(MonadAp[GB, GAB, GA, S, A, B], ga)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChainFirst[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](ma GA, f FCT) GA {
|
||||||
|
return C.MonadChainFirst(
|
||||||
|
MonadChain[GA, GA, func(A) GA],
|
||||||
|
MonadMap[GA, GB, func(B) A],
|
||||||
|
ma,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChainFirst[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](f FCT) func(GA) GA {
|
||||||
|
return C.ChainFirst(
|
||||||
|
Chain[GA, GA, func(A) GA],
|
||||||
|
Map[GA, GB, func(B) A],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flatten[GAA ~func(S) P.Pair[GA, S], GA ~func(S) P.Pair[A, S], S, A any](mma GAA) GA {
|
||||||
|
return MonadChain[GA, GAA, func(GA) GA](mma, F.Identity[GA])
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute[GA ~func(S) P.Pair[A, S], S, A any](s S) func(GA) S {
|
||||||
|
return func(fa GA) S {
|
||||||
|
return P.Tail(fa(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Evaluate[GA ~func(S) P.Pair[A, S], S, A any](s S) func(GA) A {
|
||||||
|
return func(fa GA) A {
|
||||||
|
return P.Head(fa(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadFlap[FAB ~func(A) B, GFAB ~func(S) P.Pair[FAB, S], GB ~func(S) P.Pair[B, S], S, A, B any](fab GFAB, a A) GB {
|
||||||
|
return FC.MonadFlap(
|
||||||
|
MonadMap[GB, GFAB, func(FAB) B],
|
||||||
|
fab,
|
||||||
|
a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flap[FAB ~func(A) B, GFAB ~func(S) P.Pair[FAB, S], GB ~func(S) P.Pair[B, S], S, A, B any](a A) func(GFAB) GB {
|
||||||
|
return FC.Flap(Map[GB, GFAB, func(FAB) B], a)
|
||||||
|
}
|
44
state/monad.go
Normal file
44
state/monad.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) 2024 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
G "github.com/IBM/fp-go/state/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [State]
|
||||||
|
func Pointed[S, A any]() pointed.Pointed[A, State[S, A]] {
|
||||||
|
return G.Pointed[State[S, A], S, A]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor implements the pointed operations for [State]
|
||||||
|
func Functor[S, A, B any]() functor.Functor[A, B, State[S, A], State[S, B]] {
|
||||||
|
return G.Functor[State[S, B], State[S, A], S, A, B]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative implements the applicative operations for [State]
|
||||||
|
func Applicative[S, A, B any]() applicative.Applicative[A, B, State[S, A], State[S, B], State[S, func(A) B]] {
|
||||||
|
return G.Applicative[State[S, B], State[S, func(A) B], State[S, A]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [State]
|
||||||
|
func Monad[S, A, B any]() monad.Monad[A, B, State[S, A], State[S, B], State[S, func(A) B]] {
|
||||||
|
return G.Monad[State[S, B], State[S, func(A) B], State[S, A]]()
|
||||||
|
}
|
97
state/state.go
Normal file
97
state/state.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright (c) 2024 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 state
|
||||||
|
|
||||||
|
import (
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
R "github.com/IBM/fp-go/reader"
|
||||||
|
G "github.com/IBM/fp-go/state/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// State represents an operation on top of a current [State] that produces a value and a new [State]
|
||||||
|
type State[S, A any] R.Reader[S, P.Pair[A, S]]
|
||||||
|
|
||||||
|
func Get[S any]() State[S, S] {
|
||||||
|
return G.Get[State[S, S]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Gets[FCT ~func(S) A, A, S any](f FCT) State[S, A] {
|
||||||
|
return G.Gets[State[S, A]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Put[S any]() State[S, any] {
|
||||||
|
return G.Put[State[S, any]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Modify[FCT ~func(S) S, S any](f FCT) State[S, any] {
|
||||||
|
return G.Modify[State[S, any]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Of[S, A any](a A) State[S, A] {
|
||||||
|
return G.Of[State[S, A]](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMap[S any, FCT ~func(A) B, A, B any](fa State[S, A], f FCT) State[S, B] {
|
||||||
|
return G.MonadMap[State[S, B], State[S, A]](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map[S any, FCT ~func(A) B, A, B any](f FCT) func(State[S, A]) State[S, B] {
|
||||||
|
return G.Map[State[S, B], State[S, A]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[S any, FCT ~func(A) State[S, B], A, B any](fa State[S, A], f FCT) State[S, B] {
|
||||||
|
return G.MonadChain[State[S, B], State[S, A]](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[S any, FCT ~func(A) State[S, B], A, B any](f FCT) func(State[S, A]) State[S, B] {
|
||||||
|
return G.Chain[State[S, B], State[S, A]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadAp[S, A, B any](fab State[S, func(A) B], fa State[S, A]) State[S, B] {
|
||||||
|
return G.MonadAp[State[S, B], State[S, func(A) B], State[S, A]](fab, fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ap[S, A, B any](ga State[S, A]) func(State[S, func(A) B]) State[S, B] {
|
||||||
|
return G.Ap[State[S, B], State[S, func(A) B], State[S, A]](ga)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChainFirst[S any, FCT ~func(A) State[S, B], A, B any](ma State[S, A], f FCT) State[S, A] {
|
||||||
|
return G.MonadChainFirst[State[S, B], State[S, A]](ma, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChainFirst[S any, FCT ~func(A) State[S, B], A, B any](f FCT) func(State[S, A]) State[S, A] {
|
||||||
|
return G.ChainFirst[State[S, B], State[S, A]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flatten[S, A any](mma State[S, State[S, A]]) State[S, A] {
|
||||||
|
return G.Flatten[State[S, State[S, A]], State[S, A]](mma)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute[A, S any](s S) func(State[S, A]) S {
|
||||||
|
return G.Execute[State[S, A]](s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Evaluate[A, S any](s S) func(State[S, A]) A {
|
||||||
|
return G.Evaluate[State[S, A]](s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadFlap[FAB ~func(A) B, S, A, B any](fab State[S, FAB], a A) State[S, B] {
|
||||||
|
return G.MonadFlap[FAB, State[S, FAB], State[S, B], S, A, B](fab, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flap[S, A, B any](a A) func(State[S, func(A) B]) State[S, B] {
|
||||||
|
return G.Flap[func(A) B, State[S, func(A) B], State[S, B]](a)
|
||||||
|
}
|
78
state/testing/laws.go
Normal file
78
state/testing/laws.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
// 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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
L "github.com/IBM/fp-go/internal/monad/testing"
|
||||||
|
ST "github.com/IBM/fp-go/state"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AssertLaws asserts the apply monad laws for the `Either` monad
|
||||||
|
func AssertLaws[S, A, B, C any](t *testing.T,
|
||||||
|
eqw EQ.Eq[S],
|
||||||
|
eqa EQ.Eq[A],
|
||||||
|
eqb EQ.Eq[B],
|
||||||
|
eqc EQ.Eq[C],
|
||||||
|
|
||||||
|
ab func(A) B,
|
||||||
|
bc func(B) C,
|
||||||
|
|
||||||
|
s S,
|
||||||
|
) func(a A) bool {
|
||||||
|
|
||||||
|
fofc := ST.Pointed[S, C]()
|
||||||
|
fofaa := ST.Pointed[S, func(A) A]()
|
||||||
|
fofbc := ST.Pointed[S, func(B) C]()
|
||||||
|
fofabb := ST.Pointed[S, func(func(A) B) B]()
|
||||||
|
|
||||||
|
fmap := ST.Functor[S, func(B) C, func(func(A) B) func(A) C]()
|
||||||
|
|
||||||
|
fapabb := ST.Applicative[S, func(A) B, B]()
|
||||||
|
fapabac := ST.Applicative[S, func(A) B, func(A) C]()
|
||||||
|
|
||||||
|
maa := ST.Monad[S, A, A]()
|
||||||
|
mab := ST.Monad[S, A, B]()
|
||||||
|
mac := ST.Monad[S, A, C]()
|
||||||
|
mbc := ST.Monad[S, B, C]()
|
||||||
|
|
||||||
|
return L.MonadAssertLaws(t,
|
||||||
|
ST.Eq(eqw, eqa)(s),
|
||||||
|
ST.Eq(eqw, eqb)(s),
|
||||||
|
ST.Eq(eqw, eqc)(s),
|
||||||
|
|
||||||
|
fofc,
|
||||||
|
fofaa,
|
||||||
|
fofbc,
|
||||||
|
fofabb,
|
||||||
|
|
||||||
|
fmap,
|
||||||
|
|
||||||
|
fapabb,
|
||||||
|
fapabac,
|
||||||
|
|
||||||
|
maa,
|
||||||
|
mab,
|
||||||
|
mac,
|
||||||
|
mbc,
|
||||||
|
|
||||||
|
ab,
|
||||||
|
bc,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
49
state/testing/laws_test.go
Normal file
49
state/testing/laws_test.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// 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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMonadLaws(t *testing.T) {
|
||||||
|
// some comparison
|
||||||
|
eqs := A.Eq[string](EQ.FromStrictEquals[string]())
|
||||||
|
eqa := EQ.FromStrictEquals[bool]()
|
||||||
|
eqb := EQ.FromStrictEquals[int]()
|
||||||
|
eqc := EQ.FromStrictEquals[string]()
|
||||||
|
|
||||||
|
ab := func(a bool) int {
|
||||||
|
if a {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bc := func(b int) string {
|
||||||
|
return fmt.Sprintf("value %d", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
laws := AssertLaws(t, eqs, eqa, eqb, eqc, ab, bc, A.Empty[string]())
|
||||||
|
|
||||||
|
assert.True(t, laws(true))
|
||||||
|
assert.True(t, laws(false))
|
||||||
|
}
|
35
statereaderioeither/eq.go
Normal file
35
statereaderioeither/eq.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2024 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 statereaderioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
RIOE "github.com/IBM/fp-go/readerioeither"
|
||||||
|
G "github.com/IBM/fp-go/statereaderioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Eq implements the equals predicate for values contained in the [StateReaderIOEither] monad
|
||||||
|
func Eq[
|
||||||
|
S, R, E, A any](eqr EQ.Eq[RIOE.ReaderIOEither[R, E, P.Pair[A, S]]]) func(S) EQ.Eq[StateReaderIOEither[S, R, E, A]] {
|
||||||
|
return G.Eq[StateReaderIOEither[S, R, E, A]](eqr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||||
|
func FromStrictEquals[
|
||||||
|
S, R any, E, A comparable]() func(R) func(S) EQ.Eq[StateReaderIOEither[S, R, E, A]] {
|
||||||
|
return G.FromStrictEquals[StateReaderIOEither[S, R, E, A]]()
|
||||||
|
}
|
49
statereaderioeither/generic/eq.go
Normal file
49
statereaderioeither/generic/eq.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
G "github.com/IBM/fp-go/readerioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Eq implements the equals predicate for values contained in the [StateReaderIOEither] monad
|
||||||
|
func Eq[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any](eqr EQ.Eq[RIOEA]) func(S) EQ.Eq[SRIOEA] {
|
||||||
|
return func(s S) EQ.Eq[SRIOEA] {
|
||||||
|
return EQ.FromEquals(func(l, r SRIOEA) bool {
|
||||||
|
return eqr.Equals(l(s), r(s))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||||
|
func FromStrictEquals[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R any, E, A comparable]() func(R) func(S) EQ.Eq[SRIOEA] {
|
||||||
|
return F.Flow2(
|
||||||
|
G.FromStrictEquals[RIOEA](),
|
||||||
|
Eq[SRIOEA, RIOEA, IOEA, S, R, E, A],
|
||||||
|
)
|
||||||
|
}
|
159
statereaderioeither/generic/monad.go
Normal file
159
statereaderioeither/generic/monad.go
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stateReaderIOEitherPointed[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any,
|
||||||
|
] struct{}
|
||||||
|
|
||||||
|
type stateReaderIOEitherFunctor[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
] struct{}
|
||||||
|
|
||||||
|
type stateReaderIOEitherApplicative[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
] struct{}
|
||||||
|
|
||||||
|
type stateReaderIOEitherMonad[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
] struct{}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherPointed[SRIOEA, RIOEA, IOEA, S, R, E, A]) Of(a A) SRIOEA {
|
||||||
|
return Of[SRIOEA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Of(a A) SRIOEA {
|
||||||
|
return Of[SRIOEA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Of(a A) SRIOEA {
|
||||||
|
return Of[SRIOEA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
|
||||||
|
return Map[SRIOEA, SRIOEB](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
|
||||||
|
return Map[SRIOEA, SRIOEB](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherFunctor[SRIOEA, SRIOEB, RIOEA, RIOEB, IOEA, IOEB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
|
||||||
|
return Map[SRIOEA, SRIOEB](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Chain(f func(A) SRIOEB) func(SRIOEA) SRIOEB {
|
||||||
|
return Chain[SRIOEA, SRIOEB](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Ap(fa SRIOEA) func(SRIOEAB) SRIOEB {
|
||||||
|
return Ap[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Ap(fa SRIOEA) func(SRIOEAB) SRIOEB {
|
||||||
|
return Ap[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [StateReaderIOEither]
|
||||||
|
func Pointed[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any,
|
||||||
|
]() pointed.Pointed[A, SRIOEA] {
|
||||||
|
return &stateReaderIOEitherPointed[SRIOEA, RIOEA, IOEA, S, R, E, A]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor implements the functor operations for [StateReaderIOEither]
|
||||||
|
func Functor[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
]() functor.Functor[A, B, SRIOEA, SRIOEB] {
|
||||||
|
return &stateReaderIOEitherFunctor[SRIOEA, SRIOEB, RIOEA, RIOEB, IOEA, IOEB, S, R, E, A, B]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative implements the applicative operations for [StateReaderIOEither]
|
||||||
|
func Applicative[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
]() applicative.Applicative[A, B, SRIOEA, SRIOEB, SRIOEAB] {
|
||||||
|
return &stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [StateReaderIOEither]
|
||||||
|
func Monad[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
]() monad.Monad[A, B, SRIOEA, SRIOEB, SRIOEAB] {
|
||||||
|
return &stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]{}
|
||||||
|
}
|
256
statereaderioeither/generic/state.go
Normal file
256
statereaderioeither/generic/state.go
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
ST "github.com/IBM/fp-go/internal/statet"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
G "github.com/IBM/fp-go/readerioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Left[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any,
|
||||||
|
](e E) SRIOEA {
|
||||||
|
return F.Constant1[S](G.Left[RIOEA](e))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Right[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any,
|
||||||
|
](a A) SRIOEA {
|
||||||
|
return ST.Of[SRIOEA](
|
||||||
|
G.Of[RIOEA],
|
||||||
|
a,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Of[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
S, R, E, A any,
|
||||||
|
](a A) SRIOEA {
|
||||||
|
return Right[SRIOEA](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMap[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](fa SRIOEA, f func(A) B) SRIOEB {
|
||||||
|
return ST.MonadMap[SRIOEA, SRIOEB](
|
||||||
|
G.MonadMap[RIOEA, RIOEB],
|
||||||
|
fa,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](f func(A) B) func(SRIOEA) SRIOEB {
|
||||||
|
return ST.Map[SRIOEA, SRIOEB](
|
||||||
|
G.Map[RIOEA, RIOEB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](fa SRIOEA, f func(A) SRIOEB) SRIOEB {
|
||||||
|
return ST.MonadChain[SRIOEA, SRIOEB](
|
||||||
|
G.MonadChain[RIOEA, RIOEB],
|
||||||
|
fa,
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](f func(A) SRIOEB) func(SRIOEA) SRIOEB {
|
||||||
|
return ST.Chain[SRIOEA, SRIOEB](
|
||||||
|
G.Chain[RIOEA, RIOEB],
|
||||||
|
f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadAp[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](fab SRIOEAB, fa SRIOEA) SRIOEB {
|
||||||
|
return ST.MonadAp[SRIOEA, SRIOEB, SRIOEAB](
|
||||||
|
G.MonadMap[RIOEA, RIOEB],
|
||||||
|
G.MonadChain[RIOEAB, RIOEB],
|
||||||
|
fab,
|
||||||
|
fa,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ap[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
SRIOEB ~func(S) RIOEB,
|
||||||
|
SRIOEAB ~func(S) RIOEAB,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
RIOEB ~func(R) IOEB,
|
||||||
|
RIOEAB ~func(R) IOEAB,
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEB ~func() ET.Either[E, P.Pair[B, S]],
|
||||||
|
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
|
||||||
|
S, R, E, A, B any,
|
||||||
|
](fa SRIOEA) func(SRIOEAB) SRIOEB {
|
||||||
|
return ST.Ap[SRIOEA, SRIOEB, SRIOEAB](
|
||||||
|
G.Map[RIOEA, RIOEB],
|
||||||
|
G.Chain[RIOEAB, RIOEB],
|
||||||
|
fa,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReaderIOEither[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
RIOEA_IN ~func(R) IOEA_IN,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEA_IN ~func() ET.Either[E, A],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa RIOEA_IN) SRIOEA {
|
||||||
|
return ST.FromF[SRIOEA](
|
||||||
|
G.MonadMap[RIOEA_IN, RIOEA],
|
||||||
|
fa,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReaderEither[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA_IN ~func(R) IOEA_IN,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
REA_IN ~func(R) ET.Either[E, A],
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEA_IN ~func() ET.Either[E, A],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa REA_IN) SRIOEA {
|
||||||
|
return FromReaderIOEither[SRIOEA](G.FromReaderEither[REA_IN, RIOEA_IN](fa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromIOEither[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA_IN ~func(R) IOEA_IN,
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEA_IN ~func() ET.Either[E, A],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa IOEA_IN) SRIOEA {
|
||||||
|
return FromReaderIOEither[SRIOEA](G.FromIOEither[RIOEA_IN](fa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromIO[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA_IN ~func(R) IOEA_IN,
|
||||||
|
|
||||||
|
IO_IN ~func() A,
|
||||||
|
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEA_IN ~func() ET.Either[E, A],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa IO_IN) SRIOEA {
|
||||||
|
return FromReaderIOEither[SRIOEA](G.FromIO[RIOEA_IN](fa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReader[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
RIOEA_IN ~func(R) IOEA_IN,
|
||||||
|
|
||||||
|
R_IN ~func(R) A,
|
||||||
|
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
IOEA_IN ~func() ET.Either[E, A],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa R_IN) SRIOEA {
|
||||||
|
return FromReaderIOEither[SRIOEA](G.FromReader[R_IN, RIOEA_IN](fa))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromEither[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](ma ET.Either[E, A]) SRIOEA {
|
||||||
|
return ET.MonadFold(ma, Left[SRIOEA], Right[SRIOEA])
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromState[
|
||||||
|
SRIOEA ~func(S) RIOEA,
|
||||||
|
STATE ~func(S) P.Pair[A, S],
|
||||||
|
RIOEA ~func(R) IOEA,
|
||||||
|
|
||||||
|
IOEA ~func() ET.Either[E, P.Pair[A, S]],
|
||||||
|
|
||||||
|
S, R, E, A any,
|
||||||
|
](fa STATE) SRIOEA {
|
||||||
|
return ST.FromState[SRIOEA](G.Of[RIOEA], fa)
|
||||||
|
}
|
44
statereaderioeither/monad.go
Normal file
44
statereaderioeither/monad.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) 2024 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 statereaderioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
G "github.com/IBM/fp-go/statereaderioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pointed returns the pointed operations for [StateReaderIOEither]
|
||||||
|
func Pointed[S, R, E, A any]() pointed.Pointed[A, StateReaderIOEither[S, R, E, A]] {
|
||||||
|
return G.Pointed[StateReaderIOEither[S, R, E, A]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor returns the functor operations for [StateReaderIOEither]
|
||||||
|
func Functor[S, R, E, A, B any]() functor.Functor[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]] {
|
||||||
|
return G.Functor[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative returns the applicative operations for [StateReaderIOEither]
|
||||||
|
func Applicative[S, R, E, A, B any]() applicative.Applicative[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]] {
|
||||||
|
return G.Applicative[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad returns the monadic operations for [StateReaderIOEither]
|
||||||
|
func Monad[S, R, E, A, B any]() monad.Monad[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]] {
|
||||||
|
return G.Monad[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]]()
|
||||||
|
}
|
91
statereaderioeither/state.go
Normal file
91
statereaderioeither/state.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// Copyright (c) 2024 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 statereaderioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
|
RD "github.com/IBM/fp-go/reader"
|
||||||
|
RE "github.com/IBM/fp-go/readereither"
|
||||||
|
RIOE "github.com/IBM/fp-go/readerioeither"
|
||||||
|
ST "github.com/IBM/fp-go/state"
|
||||||
|
G "github.com/IBM/fp-go/statereaderioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Left[S, R, A, E any](e E) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.Left[StateReaderIOEither[S, R, E, A]](e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Right[S, R, E, A any](a A) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.Right[StateReaderIOEither[S, R, E, A]](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Of[S, R, E, A any](a A) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.Of[StateReaderIOEither[S, R, E, A]](a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadMap[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A], f func(A) B) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.MonadMap[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Map[S, R, E, A, B any](f func(A) B) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.Map[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadChain[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A], f func(A) StateReaderIOEither[S, R, E, B]) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.MonadChain[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Chain[S, R, E, A, B any](f func(A) StateReaderIOEither[S, R, E, B]) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.Chain[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadAp[S, R, E, A, B any](fab StateReaderIOEither[S, R, E, func(A) B], fa StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.MonadAp[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]](fab, fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ap[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A]) func(StateReaderIOEither[S, R, E, func(A) B]) StateReaderIOEither[S, R, E, B] {
|
||||||
|
return G.Ap[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReaderIOEither[S, R, E, A any](fa RIOE.ReaderIOEither[R, E, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromReaderIOEither[StateReaderIOEither[S, R, E, A]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReaderEither[S, R, E, A any](fa RE.ReaderEither[R, E, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromReaderEither[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromIOEither[S, R, E, A any](fa IOE.IOEither[E, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromIOEither[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromState[S, R, E, A any](sa ST.State[S, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromState[StateReaderIOEither[S, R, E, A]](sa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromIO[S, R, E, A any](fa IO.IO[A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromIO[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromReader[S, R, E, A any](fa RD.Reader[R, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromReader[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromEither[S, R, E, A any](ma ET.Either[E, A]) StateReaderIOEither[S, R, E, A] {
|
||||||
|
return G.FromEither[StateReaderIOEither[S, R, E, A]](ma)
|
||||||
|
}
|
87
statereaderioeither/testing/laws.go
Normal file
87
statereaderioeither/testing/laws.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright (c) 2024 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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
ET "github.com/IBM/fp-go/either"
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
L "github.com/IBM/fp-go/internal/monad/testing"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
RIOE "github.com/IBM/fp-go/readerioeither"
|
||||||
|
ST "github.com/IBM/fp-go/statereaderioeither"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AssertLaws asserts the apply monad laws for the `Either` monad
|
||||||
|
func AssertLaws[S, E, R, A, B, C any](t *testing.T,
|
||||||
|
eqs EQ.Eq[S],
|
||||||
|
eqe EQ.Eq[E],
|
||||||
|
eqa EQ.Eq[A],
|
||||||
|
eqb EQ.Eq[B],
|
||||||
|
eqc EQ.Eq[C],
|
||||||
|
|
||||||
|
ab func(A) B,
|
||||||
|
bc func(B) C,
|
||||||
|
|
||||||
|
s S,
|
||||||
|
r R,
|
||||||
|
) func(a A) bool {
|
||||||
|
|
||||||
|
eqra := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqa, eqs)))(r)
|
||||||
|
eqrb := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqb, eqs)))(r)
|
||||||
|
eqrc := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqc, eqs)))(r)
|
||||||
|
|
||||||
|
fofc := ST.Pointed[S, R, E, C]()
|
||||||
|
fofaa := ST.Pointed[S, R, E, func(A) A]()
|
||||||
|
fofbc := ST.Pointed[S, R, E, func(B) C]()
|
||||||
|
fofabb := ST.Pointed[S, R, E, func(func(A) B) B]()
|
||||||
|
|
||||||
|
fmap := ST.Functor[S, R, E, func(B) C, func(func(A) B) func(A) C]()
|
||||||
|
|
||||||
|
fapabb := ST.Applicative[S, R, E, func(A) B, B]()
|
||||||
|
fapabac := ST.Applicative[S, R, E, func(A) B, func(A) C]()
|
||||||
|
|
||||||
|
maa := ST.Monad[S, R, E, A, A]()
|
||||||
|
mab := ST.Monad[S, R, E, A, B]()
|
||||||
|
mac := ST.Monad[S, R, E, A, C]()
|
||||||
|
mbc := ST.Monad[S, R, E, B, C]()
|
||||||
|
|
||||||
|
return L.MonadAssertLaws(t,
|
||||||
|
ST.Eq(eqra)(s),
|
||||||
|
ST.Eq(eqrb)(s),
|
||||||
|
ST.Eq(eqrc)(s),
|
||||||
|
|
||||||
|
fofc,
|
||||||
|
fofaa,
|
||||||
|
fofbc,
|
||||||
|
fofabb,
|
||||||
|
|
||||||
|
fmap,
|
||||||
|
|
||||||
|
fapabb,
|
||||||
|
fapabac,
|
||||||
|
|
||||||
|
maa,
|
||||||
|
mab,
|
||||||
|
mac,
|
||||||
|
mbc,
|
||||||
|
|
||||||
|
ab,
|
||||||
|
bc,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
51
statereaderioeither/testing/laws_test.go
Normal file
51
statereaderioeither/testing/laws_test.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// 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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMonadLaws(t *testing.T) {
|
||||||
|
// some comparison
|
||||||
|
eqs := A.Eq[string](EQ.FromStrictEquals[string]())
|
||||||
|
eqe := EQ.FromStrictEquals[error]()
|
||||||
|
eqa := EQ.FromStrictEquals[bool]()
|
||||||
|
eqb := EQ.FromStrictEquals[int]()
|
||||||
|
eqc := EQ.FromStrictEquals[string]()
|
||||||
|
|
||||||
|
ab := func(a bool) int {
|
||||||
|
if a {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bc := func(b int) string {
|
||||||
|
return fmt.Sprintf("value %d", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
laws := AssertLaws(t, eqs, eqe, eqa, eqb, eqc, ab, bc, A.Empty[string](), context.Background())
|
||||||
|
|
||||||
|
assert.True(t, laws(true))
|
||||||
|
assert.True(t, laws(false))
|
||||||
|
}
|
24
statereaderioeither/type.go
Normal file
24
statereaderioeither/type.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2024 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 statereaderioeither
|
||||||
|
|
||||||
|
import (
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
RD "github.com/IBM/fp-go/reader"
|
||||||
|
RIOE "github.com/IBM/fp-go/readerioeither"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StateReaderIOEither[S, R, E, A any] RD.Reader[S, RIOE.ReaderIOEither[R, E, P.Pair[A, S]]]
|
@@ -17,20 +17,22 @@ package writer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
SG "github.com/IBM/fp-go/semigroup"
|
||||||
G "github.com/IBM/fp-go/writer/generic"
|
G "github.com/IBM/fp-go/writer/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||||
func Do[S, W any](m M.Monoid[W]) func(S) Writer[W, S] {
|
func Do[S, W any](m M.Monoid[W], s S) Writer[W, S] {
|
||||||
return G.Do[Writer[W, S], W, S](m)
|
return G.Do[Writer[W, S], W, S](m, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||||
func Bind[S1, S2, T, W any](
|
func Bind[S1, S2, T, W any](
|
||||||
|
s SG.Semigroup[W],
|
||||||
setter func(T) func(S1) S2,
|
setter func(T) func(S1) S2,
|
||||||
f func(S1) Writer[W, T],
|
f func(S1) Writer[W, T],
|
||||||
) func(Writer[W, S1]) Writer[W, S2] {
|
) func(Writer[W, S1]) Writer[W, S2] {
|
||||||
return G.Bind[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](setter, f)
|
return G.Bind[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](s, setter, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||||
@@ -58,8 +60,9 @@ func BindTo[W, S1, T any](
|
|||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
||||||
func ApS[S1, S2, T, W any](
|
func ApS[S1, S2, T, W any](
|
||||||
|
s SG.Semigroup[W],
|
||||||
setter func(T) func(S1) S2,
|
setter func(T) func(S1) S2,
|
||||||
fa Writer[W, T],
|
fa Writer[W, T],
|
||||||
) func(Writer[W, S1]) Writer[W, S2] {
|
) func(Writer[W, S1]) Writer[W, S2] {
|
||||||
return G.ApS[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](setter, fa)
|
return G.ApS[Writer[W, S1], Writer[W, S2], Writer[W, T], W, S1, S2, T](s, setter, fa)
|
||||||
}
|
}
|
||||||
|
@@ -34,33 +34,33 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func getLastName(s utils.Initial) Writer[[]string, string] {
|
func getLastName(s utils.Initial) Writer[[]string, string] {
|
||||||
return Of[string](monoid)("Doe")
|
return Of[string](monoid, "Doe")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) Writer[[]string, string] {
|
func getGivenName(s utils.WithLastName) Writer[[]string, string] {
|
||||||
return Of[string](monoid)("John")
|
return Of[string](monoid, "John")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
func TestBind(t *testing.T) {
|
||||||
|
|
||||||
res := F.Pipe3(
|
res := F.Pipe3(
|
||||||
Do[utils.Initial](monoid)(utils.Empty),
|
Do[utils.Initial](monoid, utils.Empty),
|
||||||
Bind(utils.SetLastName, getLastName),
|
Bind(sg, utils.SetLastName, getLastName),
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
Bind(sg, utils.SetGivenName, getGivenName),
|
||||||
Map[[]string](utils.GetFullName),
|
Map[[]string](utils.GetFullName),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.True(t, eq.Equals(res, Of[string](monoid)("John Doe")))
|
assert.True(t, eq.Equals(res, Of[string](monoid, "John Doe")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
func TestApS(t *testing.T) {
|
||||||
|
|
||||||
res := F.Pipe3(
|
res := F.Pipe3(
|
||||||
Do[utils.Initial](monoid)(utils.Empty),
|
Do[utils.Initial](monoid, utils.Empty),
|
||||||
ApS(utils.SetLastName, Of[string](monoid)("Doe")),
|
ApS(sg, utils.SetLastName, Of[string](monoid, "Doe")),
|
||||||
ApS(utils.SetGivenName, Of[string](monoid)("John")),
|
ApS(sg, utils.SetGivenName, Of[string](monoid, "John")),
|
||||||
Map[[]string](utils.GetFullName),
|
Map[[]string](utils.GetFullName),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.True(t, eq.Equals(res, Of[string](monoid)("John Doe")))
|
assert.True(t, eq.Equals(res, Of[string](monoid, "John Doe")))
|
||||||
}
|
}
|
||||||
|
@@ -16,26 +16,28 @@
|
|||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
FCT "github.com/IBM/fp-go/function"
|
||||||
"github.com/IBM/fp-go/internal/apply"
|
"github.com/IBM/fp-go/internal/apply"
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
C "github.com/IBM/fp-go/internal/chain"
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
F "github.com/IBM/fp-go/internal/functor"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
SG "github.com/IBM/fp-go/semigroup"
|
SG "github.com/IBM/fp-go/semigroup"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||||
func Do[GS ~func() T.Tuple3[S, W, SG.Semigroup[W]], W, S any](m M.Monoid[W]) func(S) GS {
|
func Do[GS ~func() P.Pair[S, W], W, S any](m M.Monoid[W], s S) GS {
|
||||||
return Of[GS, W, S](m)
|
return Of[GS, W, S](m, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||||
func Bind[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, S2, A any](
|
func Bind[GS1 ~func() P.Pair[S1, W], GS2 ~func() P.Pair[S2, W], GT ~func() P.Pair[A, W], W, S1, S2, A any](
|
||||||
|
s SG.Semigroup[W],
|
||||||
setter func(A) func(S1) S2,
|
setter func(A) func(S1) S2,
|
||||||
f func(S1) GT,
|
f func(S1) GT,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
return C.Bind(
|
return C.Bind(
|
||||||
Chain[GS2, GS1, func(S1) GS2, W, S1, S2],
|
FCT.Bind1st(Chain[GS2, GS1, func(S1) GS2, W, S1, S2], s),
|
||||||
Map[GS2, GT, func(A) S2, W, A, S2],
|
Map[GS2, GT, func(A) S2, W, A, S2],
|
||||||
setter,
|
setter,
|
||||||
f,
|
f,
|
||||||
@@ -43,7 +45,7 @@ func Bind[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||||
func Let[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], W, S1, S2, A any](
|
func Let[GS1 ~func() P.Pair[S1, W], GS2 ~func() P.Pair[S2, W], W, S1, S2, A any](
|
||||||
key func(A) func(S1) S2,
|
key func(A) func(S1) S2,
|
||||||
f func(S1) A,
|
f func(S1) A,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
@@ -55,7 +57,7 @@ func Let[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
||||||
func LetTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], W, S1, S2, B any](
|
func LetTo[GS1 ~func() P.Pair[S1, W], GS2 ~func() P.Pair[S2, W], W, S1, S2, B any](
|
||||||
key func(B) func(S1) S2,
|
key func(B) func(S1) S2,
|
||||||
b B,
|
b B,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
@@ -67,7 +69,7 @@ func LetTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
// BindTo initializes a new state [S1] from a value [T]
|
||||||
func BindTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, A any](
|
func BindTo[GS1 ~func() P.Pair[S1, W], GT ~func() P.Pair[A, W], W, S1, A any](
|
||||||
setter func(A) S1,
|
setter func(A) S1,
|
||||||
) func(GT) GS1 {
|
) func(GT) GS1 {
|
||||||
return C.BindTo(
|
return C.BindTo(
|
||||||
@@ -77,13 +79,14 @@ func BindTo[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
||||||
func ApS[GS1 ~func() T.Tuple3[S1, W, SG.Semigroup[W]], GS2 ~func() T.Tuple3[S2, W, SG.Semigroup[W]], GT ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, S1, S2, A any](
|
func ApS[GS1 ~func() P.Pair[S1, W], GS2 ~func() P.Pair[S2, W], GT ~func() P.Pair[A, W], W, S1, S2, A any](
|
||||||
|
s SG.Semigroup[W],
|
||||||
setter func(A) func(S1) S2,
|
setter func(A) func(S1) S2,
|
||||||
fa GT,
|
fa GT,
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
return apply.ApS(
|
return apply.ApS(
|
||||||
Ap[GS2, func() T.Tuple3[func(A) S2, W, SG.Semigroup[W]], GT, W, A, S2],
|
FCT.Bind1st(Ap[GS2, func() P.Pair[func(A) S2, W], GT, W, A, S2], s),
|
||||||
Map[func() T.Tuple3[func(A) S2, W, SG.Semigroup[W]], GS1, func(S1) func(A) S2],
|
Map[func() P.Pair[func(A) S2, W], GS1, func(S1) func(A) S2],
|
||||||
setter,
|
setter,
|
||||||
fa,
|
fa,
|
||||||
)
|
)
|
||||||
|
@@ -17,21 +17,18 @@ package generic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
EQ "github.com/IBM/fp-go/eq"
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
SG "github.com/IBM/fp-go/semigroup"
|
P "github.com/IBM/fp-go/pair"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constructs an equal predicate for a [Writer]
|
// Constructs an equal predicate for a [Writer]
|
||||||
func Eq[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](w EQ.Eq[W], a EQ.Eq[A]) EQ.Eq[GA] {
|
func Eq[GA ~func() P.Pair[A, W], W, A any](w EQ.Eq[W], a EQ.Eq[A]) EQ.Eq[GA] {
|
||||||
|
eqp := P.Eq(a, w)
|
||||||
return EQ.FromEquals(func(l, r GA) bool {
|
return EQ.FromEquals(func(l, r GA) bool {
|
||||||
ll := l()
|
return eqp.Equals(l(), r())
|
||||||
rr := r()
|
|
||||||
|
|
||||||
return a.Equals(ll.F1, rr.F1) && w.Equals(ll.F2, rr.F2)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||||
func FromStrictEquals[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A comparable]() EQ.Eq[GA] {
|
func FromStrictEquals[GA ~func() P.Pair[A, W], W, A comparable]() EQ.Eq[GA] {
|
||||||
return Eq[GA](EQ.FromStrictEquals[W](), EQ.FromStrictEquals[A]())
|
return Eq[GA](EQ.FromStrictEquals[W](), EQ.FromStrictEquals[A]())
|
||||||
}
|
}
|
||||||
|
106
writer/generic/monad.go
Normal file
106
writer/generic/monad.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2024 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
|
SG "github.com/IBM/fp-go/semigroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
type writerPointed[GA ~func() P.Pair[A, W], W, A any] struct {
|
||||||
|
m M.Monoid[W]
|
||||||
|
}
|
||||||
|
|
||||||
|
type writerFunctor[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], W, A, B any] struct{}
|
||||||
|
|
||||||
|
type writerApplicative[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any] struct {
|
||||||
|
s SG.Semigroup[W]
|
||||||
|
m M.Monoid[W]
|
||||||
|
}
|
||||||
|
|
||||||
|
type writerMonad[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any] struct {
|
||||||
|
s SG.Semigroup[W]
|
||||||
|
m M.Monoid[W]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerPointed[GA, W, A]) Of(a A) GA {
|
||||||
|
return Of[GA](o.m, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerApplicative[GB, GAB, GA, W, A, B]) Of(a A) GA {
|
||||||
|
return Of[GA](o.m, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerMonad[GB, GAB, GA, W, A, B]) Of(a A) GA {
|
||||||
|
return Of[GA](o.m, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerFunctor[GB, GA, W, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerApplicative[GB, GAB, GA, W, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerMonad[GB, GAB, GA, W, A, B]) Map(f func(A) B) func(GA) GB {
|
||||||
|
return Map[GB, GA](f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerMonad[GB, GAB, GA, W, A, B]) Chain(f func(A) GB) func(GA) GB {
|
||||||
|
return Chain[GB, GA](o.s, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerApplicative[GB, GAB, GA, W, A, B]) Ap(fa GA) func(GAB) GB {
|
||||||
|
return Ap[GB, GAB, GA](o.s, fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *writerMonad[GB, GAB, GA, W, A, B]) Ap(fa GA) func(GAB) GB {
|
||||||
|
return Ap[GB, GAB, GA](o.s, fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [Writer]
|
||||||
|
func Pointed[GA ~func() P.Pair[A, W], W, A any](m M.Monoid[W]) pointed.Pointed[A, GA] {
|
||||||
|
return &writerPointed[GA, W, A]{
|
||||||
|
m: m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor implements the functor operations for [Writer]
|
||||||
|
func Functor[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], W, A, B any]() functor.Functor[A, B, GA, GB] {
|
||||||
|
return &writerFunctor[GB, GA, W, A, B]{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative implements the applicative operations for [Writer]
|
||||||
|
func Applicative[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any](m M.Monoid[W]) applicative.Applicative[A, B, GA, GB, GAB] {
|
||||||
|
return &writerApplicative[GB, GAB, GA, W, A, B]{
|
||||||
|
s: M.ToSemigroup(m),
|
||||||
|
m: m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [Writer]
|
||||||
|
func Monad[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any](m M.Monoid[W]) monad.Monad[A, B, GA, GB, GAB] {
|
||||||
|
return &writerMonad[GB, GAB, GA, W, A, B]{
|
||||||
|
s: M.ToSemigroup(m),
|
||||||
|
m: m,
|
||||||
|
}
|
||||||
|
}
|
@@ -21,133 +21,137 @@ import (
|
|||||||
FC "github.com/IBM/fp-go/internal/functor"
|
FC "github.com/IBM/fp-go/internal/functor"
|
||||||
IO "github.com/IBM/fp-go/io/generic"
|
IO "github.com/IBM/fp-go/io/generic"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
P "github.com/IBM/fp-go/pair"
|
||||||
SG "github.com/IBM/fp-go/semigroup"
|
SG "github.com/IBM/fp-go/semigroup"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Tell[GA ~func() T.Tuple3[any, W, SG.Semigroup[W]], W any](s SG.Semigroup[W]) func(W) GA {
|
var (
|
||||||
return F.Flow2(
|
undefined any = struct{}{}
|
||||||
F.Bind13of3(T.MakeTuple3[any, W, SG.Semigroup[W]])(nil, s),
|
)
|
||||||
IO.Of[GA],
|
|
||||||
)
|
func Tell[GA ~func() P.Pair[any, W], W any](w W) GA {
|
||||||
|
return IO.Of[GA](P.MakePair[any](undefined, w))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Of[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](m M.Monoid[W]) func(A) GA {
|
func Of[GA ~func() P.Pair[A, W], W, A any](m M.Monoid[W], a A) GA {
|
||||||
return F.Flow2(
|
return IO.Of[GA](P.MakePair(a, m.Empty()))
|
||||||
F.Bind23of3(T.MakeTuple3[A, W, SG.Semigroup[W]])(m.Empty(), M.ToSemigroup(m)),
|
|
||||||
IO.Of[GA],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen modifies the result to include the changes to the accumulator
|
// Listen modifies the result to include the changes to the accumulator
|
||||||
func Listen[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GTA ~func() T.Tuple3[T.Tuple2[A, W], W, SG.Semigroup[W]], W, A any](fa GA) GTA {
|
func Listen[GA ~func() P.Pair[A, W], GTA ~func() P.Pair[P.Pair[A, W], W], W, A any](fa GA) GTA {
|
||||||
return func() T.Tuple3[T.Tuple2[A, W], W, SG.Semigroup[W]] {
|
return func() P.Pair[P.Pair[A, W], W] {
|
||||||
t := fa()
|
t := fa()
|
||||||
return T.MakeTuple3(T.MakeTuple2(t.F1, t.F2), t.F2, t.F3)
|
return P.MakePair(t, P.Tail(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass applies the returned function to the accumulator
|
// Pass applies the returned function to the accumulator
|
||||||
func Pass[GFA ~func() T.Tuple3[T.Tuple2[A, FCT], W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](fa GFA) GA {
|
func Pass[GFA ~func() P.Pair[P.Pair[A, FCT], W], GA ~func() P.Pair[A, W], FCT ~func(W) W, W, A any](fa GFA) GA {
|
||||||
return func() T.Tuple3[A, W, SG.Semigroup[W]] {
|
return func() P.Pair[A, W] {
|
||||||
t := fa()
|
t := fa()
|
||||||
return T.MakeTuple3(t.F1.F1, t.F1.F2(t.F2), t.F3)
|
a := P.Head(t)
|
||||||
|
return P.MakePair(P.Head(a), P.Tail(a)(P.Tail(t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMap[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) B, W, A, B any](fa GA, f FCT) GB {
|
func MonadMap[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) B, W, A, B any](fa GA, f FCT) GB {
|
||||||
return IO.MonadMap[GA, GB](fa, T.Map3(f, F.Identity[W], F.Identity[SG.Semigroup[W]]))
|
return IO.MonadMap[GA, GB](fa, P.Map[W](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) B, W, A, B any](f FCT) func(GA) GB {
|
func Map[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) B, W, A, B any](f FCT) func(GA) GB {
|
||||||
return IO.Map[GA, GB](T.Map3(f, F.Identity[W], F.Identity[SG.Semigroup[W]]))
|
return IO.Map[GA, GB](P.Map[W](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChain[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](fa GA, f FCT) GB {
|
func MonadChain[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) GB, W, A, B any](s SG.Semigroup[W], fa GA, f FCT) GB {
|
||||||
return func() T.Tuple3[B, W, SG.Semigroup[W]] {
|
return func() P.Pair[B, W] {
|
||||||
a := fa()
|
a := fa()
|
||||||
b := f(a.F1)()
|
b := f(P.Head(a))()
|
||||||
|
|
||||||
return T.MakeTuple3(b.F1, b.F3.Concat(a.F2, b.F2), b.F3)
|
return P.MakePair(P.Head(b), s.Concat(P.Tail(a), P.Tail(b)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chain[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](f FCT) func(GA) GB {
|
func Chain[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) GB, W, A, B any](s SG.Semigroup[W], f FCT) func(GA) GB {
|
||||||
return F.Bind2nd(MonadChain[GB, GA, FCT, W, A, B], f)
|
return func(fa GA) GB {
|
||||||
|
return MonadChain(s, fa, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[func(A) B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A, B any](fab GAB, fa GA) GB {
|
func MonadAp[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any](s SG.Semigroup[W], fab GAB, fa GA) GB {
|
||||||
return func() T.Tuple3[B, W, SG.Semigroup[W]] {
|
return func() P.Pair[B, W] {
|
||||||
f := fab()
|
f := fab()
|
||||||
a := fa()
|
a := fa()
|
||||||
|
|
||||||
return T.MakeTuple3(f.F1(a.F1), f.F3.Concat(f.F2, a.F2), f.F3)
|
return P.MakePair(P.Head(f)(P.Head(a)), s.Concat(P.Tail(f), P.Tail(a)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ap[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[func(A) B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A, B any](ga GA) func(GAB) GB {
|
func Ap[GB ~func() P.Pair[B, W], GAB ~func() P.Pair[func(A) B, W], GA ~func() P.Pair[A, W], W, A, B any](s SG.Semigroup[W], ga GA) func(GAB) GB {
|
||||||
return F.Bind2nd(MonadAp[GB, GAB, GA], ga)
|
return func(fab GAB) GB {
|
||||||
|
return MonadAp[GB](s, fab, ga)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainFirst[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](ma GA, f FCT) GA {
|
func MonadChainFirst[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) GB, W, A, B any](s SG.Semigroup[W], ma GA, f FCT) GA {
|
||||||
return C.MonadChainFirst(
|
return C.MonadChainFirst(
|
||||||
MonadChain[GA, GA, func(A) GA],
|
F.Bind1of3(MonadChain[GA, GA, func(A) GA])(s),
|
||||||
MonadMap[GA, GB, func(B) A],
|
MonadMap[GA, GB, func(B) A],
|
||||||
ma,
|
ma,
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChainFirst[GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(A) GB, W, A, B any](f FCT) func(GA) GA {
|
func ChainFirst[GB ~func() P.Pair[B, W], GA ~func() P.Pair[A, W], FCT ~func(A) GB, W, A, B any](s SG.Semigroup[W], f FCT) func(GA) GA {
|
||||||
return C.ChainFirst(
|
return C.ChainFirst(
|
||||||
Chain[GA, GA, func(A) GA],
|
F.Bind1st(Chain[GA, GA, func(A) GA], s),
|
||||||
Map[GA, GB, func(B) A],
|
Map[GA, GB, func(B) A],
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flatten[GAA ~func() T.Tuple3[GA, W, SG.Semigroup[W]], GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](mma GAA) GA {
|
func Flatten[GAA ~func() P.Pair[GA, W], GA ~func() P.Pair[A, W], W, A any](s SG.Semigroup[W], mma GAA) GA {
|
||||||
return MonadChain[GA, GAA, func(GA) GA](mma, F.Identity[GA])
|
return MonadChain[GA, GAA, func(GA) GA](s, mma, F.Identity[GA])
|
||||||
}
|
}
|
||||||
|
|
||||||
func Execute[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](fa GA) W {
|
func Execute[GA ~func() P.Pair[A, W], W, A any](fa GA) W {
|
||||||
return fa().F2
|
return P.Tail(fa())
|
||||||
}
|
}
|
||||||
|
|
||||||
func Evaluate[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], W, A any](fa GA) A {
|
func Evaluate[GA ~func() P.Pair[A, W], W, A any](fa GA) A {
|
||||||
return fa().F1
|
return P.Head(fa())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadCensor modifies the final accumulator value by applying a function
|
// MonadCensor modifies the final accumulator value by applying a function
|
||||||
func MonadCensor[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](fa GA, f FCT) GA {
|
func MonadCensor[GA ~func() P.Pair[A, W], FCT ~func(W) W, W, A any](fa GA, f FCT) GA {
|
||||||
return IO.MonadMap[GA, GA](fa, T.Map3(F.Identity[A], f, F.Identity[SG.Semigroup[W]]))
|
return IO.MonadMap[GA, GA](fa, P.MapTail[A](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Censor modifies the final accumulator value by applying a function
|
// Censor modifies the final accumulator value by applying a function
|
||||||
func Censor[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], FCT ~func(W) W, W, A any](f FCT) func(GA) GA {
|
func Censor[GA ~func() P.Pair[A, W], FCT ~func(W) W, W, A any](f FCT) func(GA) GA {
|
||||||
return IO.Map[GA, GA](T.Map3(F.Identity[A], f, F.Identity[SG.Semigroup[W]]))
|
return IO.Map[GA, GA](P.MapTail[A](f))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadListens projects a value from modifications made to the accumulator during an action
|
// MonadListens projects a value from modifications made to the accumulator during an action
|
||||||
func MonadListens[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]], FCT ~func(W) B, W, A, B any](fa GA, f FCT) GAB {
|
func MonadListens[GA ~func() P.Pair[A, W], GAB ~func() P.Pair[P.Pair[A, B], W], FCT ~func(W) B, W, A, B any](fa GA, f FCT) GAB {
|
||||||
return func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]] {
|
return func() P.Pair[P.Pair[A, B], W] {
|
||||||
a := fa()
|
a := fa()
|
||||||
return T.MakeTuple3(T.MakeTuple2(a.F1, f(a.F2)), a.F2, a.F3)
|
t := P.Tail(a)
|
||||||
|
return P.MakePair(P.MakePair(P.Head(a), f(t)), t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listens projects a value from modifications made to the accumulator during an action
|
// Listens projects a value from modifications made to the accumulator during an action
|
||||||
func Listens[GA ~func() T.Tuple3[A, W, SG.Semigroup[W]], GAB ~func() T.Tuple3[T.Tuple2[A, B], W, SG.Semigroup[W]], FCT ~func(W) B, W, A, B any](f FCT) func(GA) GAB {
|
func Listens[GA ~func() P.Pair[A, W], GAB ~func() P.Pair[P.Pair[A, B], W], FCT ~func(W) B, W, A, B any](f FCT) func(GA) GAB {
|
||||||
return F.Bind2nd(MonadListens[GA, GAB, FCT], f)
|
return F.Bind2nd(MonadListens[GA, GAB, FCT], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFlap[FAB ~func(A) B, GFAB ~func() T.Tuple3[FAB, W, SG.Semigroup[W]], GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], W, A, B any](fab GFAB, a A) GB {
|
func MonadFlap[FAB ~func(A) B, GFAB ~func() P.Pair[FAB, W], GB ~func() P.Pair[B, W], W, A, B any](fab GFAB, a A) GB {
|
||||||
return FC.MonadFlap(
|
return FC.MonadFlap(
|
||||||
MonadMap[GB, GFAB, func(FAB) B],
|
MonadMap[GB, GFAB, func(FAB) B],
|
||||||
fab,
|
fab,
|
||||||
a)
|
a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flap[FAB ~func(A) B, GFAB ~func() T.Tuple3[FAB, W, SG.Semigroup[W]], GB ~func() T.Tuple3[B, W, SG.Semigroup[W]], W, A, B any](a A) func(GFAB) GB {
|
func Flap[FAB ~func(A) B, GFAB ~func() P.Pair[FAB, W], GB ~func() P.Pair[B, W], W, A, B any](a A) func(GFAB) GB {
|
||||||
return FC.Flap(Map[GB, GFAB, func(FAB) B], a)
|
return FC.Flap(Map[GB, GFAB, func(FAB) B], a)
|
||||||
}
|
}
|
||||||
|
45
writer/monad.go
Normal file
45
writer/monad.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2024 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 writer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IBM/fp-go/internal/applicative"
|
||||||
|
"github.com/IBM/fp-go/internal/functor"
|
||||||
|
"github.com/IBM/fp-go/internal/monad"
|
||||||
|
"github.com/IBM/fp-go/internal/pointed"
|
||||||
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
G "github.com/IBM/fp-go/writer/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pointed implements the pointed operations for [Writer]
|
||||||
|
func Pointed[W, A any](m M.Monoid[W]) pointed.Pointed[A, Writer[W, A]] {
|
||||||
|
return G.Pointed[Writer[W, A], W, A](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functor implements the pointed operations for [Writer]
|
||||||
|
func Functor[W, A, B any]() functor.Functor[A, B, Writer[W, A], Writer[W, B]] {
|
||||||
|
return G.Functor[Writer[W, B], Writer[W, A], W, A, B]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicative implements the applicative operations for [Writer]
|
||||||
|
func Applicative[W, A, B any](m M.Monoid[W]) applicative.Applicative[A, B, Writer[W, A], Writer[W, B], Writer[W, func(A) B]] {
|
||||||
|
return G.Applicative[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monad implements the monadic operations for [Writer]
|
||||||
|
func Monad[W, A, B any](m M.Monoid[W]) monad.Monad[A, B, Writer[W, A], Writer[W, B], Writer[W, func(A) B]] {
|
||||||
|
return G.Monad[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](m)
|
||||||
|
}
|
@@ -37,39 +37,40 @@ func AssertLaws[W, A, B, C any](t *testing.T,
|
|||||||
bc func(B) C,
|
bc func(B) C,
|
||||||
) func(a A) bool {
|
) func(a A) bool {
|
||||||
|
|
||||||
return L.AssertLaws(t,
|
fofc := WRT.Pointed[W, C](m)
|
||||||
|
fofaa := WRT.Pointed[W, func(A) A](m)
|
||||||
|
fofbc := WRT.Pointed[W, func(B) C](m)
|
||||||
|
fofabb := WRT.Pointed[W, func(func(A) B) B](m)
|
||||||
|
|
||||||
|
fmap := WRT.Functor[W, func(B) C, func(func(A) B) func(A) C]()
|
||||||
|
|
||||||
|
fapabb := WRT.Applicative[W, func(A) B, B](m)
|
||||||
|
fapabac := WRT.Applicative[W, func(A) B, func(A) C](m)
|
||||||
|
|
||||||
|
maa := WRT.Monad[W, A, A](m)
|
||||||
|
mab := WRT.Monad[W, A, B](m)
|
||||||
|
mac := WRT.Monad[W, A, C](m)
|
||||||
|
mbc := WRT.Monad[W, B, C](m)
|
||||||
|
|
||||||
|
return L.MonadAssertLaws(t,
|
||||||
WRT.Eq(eqw, eqa),
|
WRT.Eq(eqw, eqa),
|
||||||
WRT.Eq(eqw, eqb),
|
WRT.Eq(eqw, eqb),
|
||||||
WRT.Eq(eqw, eqc),
|
WRT.Eq(eqw, eqc),
|
||||||
|
|
||||||
WRT.Of[A](m),
|
fofc,
|
||||||
WRT.Of[B](m),
|
fofaa,
|
||||||
WRT.Of[C](m),
|
fofbc,
|
||||||
|
fofabb,
|
||||||
|
|
||||||
WRT.Of[func(A) A](m),
|
fmap,
|
||||||
WRT.Of[func(A) B](m),
|
|
||||||
WRT.Of[func(B) C](m),
|
|
||||||
WRT.Of[func(func(A) B) B](m),
|
|
||||||
|
|
||||||
WRT.MonadMap[func(A) A, W, A, A],
|
fapabb,
|
||||||
WRT.MonadMap[func(A) B, W, A, B],
|
fapabac,
|
||||||
WRT.MonadMap[func(A) C, W, A, C],
|
|
||||||
WRT.MonadMap[func(B) C, W, B, C],
|
|
||||||
|
|
||||||
WRT.MonadMap[func(func(B) C) func(func(A) B) func(A) C, W, func(B) C, func(func(A) B) func(A) C],
|
maa,
|
||||||
|
mab,
|
||||||
WRT.MonadChain[func(A) WRT.Writer[W, A], W, A, A],
|
mac,
|
||||||
WRT.MonadChain[func(A) WRT.Writer[W, B], W, A, B],
|
mbc,
|
||||||
WRT.MonadChain[func(A) WRT.Writer[W, C], W, A, C],
|
|
||||||
WRT.MonadChain[func(B) WRT.Writer[W, C], W, B, C],
|
|
||||||
|
|
||||||
WRT.MonadAp[A, A, W],
|
|
||||||
WRT.MonadAp[B, A, W],
|
|
||||||
WRT.MonadAp[C, B, W],
|
|
||||||
WRT.MonadAp[C, A, W],
|
|
||||||
|
|
||||||
WRT.MonadAp[B, func(A) B, W],
|
|
||||||
WRT.MonadAp[func(A) C, func(A) B, W],
|
|
||||||
|
|
||||||
ab,
|
ab,
|
||||||
bc,
|
bc,
|
||||||
|
@@ -19,30 +19,30 @@ import (
|
|||||||
EM "github.com/IBM/fp-go/endomorphism"
|
EM "github.com/IBM/fp-go/endomorphism"
|
||||||
IO "github.com/IBM/fp-go/io"
|
IO "github.com/IBM/fp-go/io"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
P "github.com/IBM/fp-go/pair"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
SG "github.com/IBM/fp-go/semigroup"
|
||||||
G "github.com/IBM/fp-go/writer/generic"
|
G "github.com/IBM/fp-go/writer/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Writer[W, A any] IO.IO[T.Tuple3[A, W, S.Semigroup[W]]]
|
type Writer[W, A any] IO.IO[P.Pair[A, W]]
|
||||||
|
|
||||||
// Tell appends a value to the accumulator
|
// Tell appends a value to the accumulator
|
||||||
func Tell[W any](s S.Semigroup[W]) func(W) Writer[W, any] {
|
func Tell[W any](w W) Writer[W, any] {
|
||||||
return G.Tell[Writer[W, any]](s)
|
return G.Tell[Writer[W, any]](w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Of[A, W any](m M.Monoid[W]) func(A) Writer[W, A] {
|
func Of[A, W any](m M.Monoid[W], a A) Writer[W, A] {
|
||||||
return G.Of[Writer[W, A]](m)
|
return G.Of[Writer[W, A]](m, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen modifies the result to include the changes to the accumulator
|
// Listen modifies the result to include the changes to the accumulator
|
||||||
func Listen[W, A any](fa Writer[W, A]) Writer[W, T.Tuple2[A, W]] {
|
func Listen[W, A any](fa Writer[W, A]) Writer[W, P.Pair[A, W]] {
|
||||||
return G.Listen[Writer[W, A], Writer[W, T.Tuple2[A, W]], W, A](fa)
|
return G.Listen[Writer[W, A], Writer[W, P.Pair[A, W]], W, A](fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass applies the returned function to the accumulator
|
// Pass applies the returned function to the accumulator
|
||||||
func Pass[W, A any](fa Writer[W, T.Tuple2[A, EM.Endomorphism[W]]]) Writer[W, A] {
|
func Pass[W, A any](fa Writer[W, P.Pair[A, EM.Endomorphism[W]]]) Writer[W, A] {
|
||||||
return G.Pass[Writer[W, T.Tuple2[A, EM.Endomorphism[W]]], Writer[W, A]](fa)
|
return G.Pass[Writer[W, P.Pair[A, EM.Endomorphism[W]]], Writer[W, A]](fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMap[FCT ~func(A) B, W, A, B any](fa Writer[W, A], f FCT) Writer[W, B] {
|
func MonadMap[FCT ~func(A) B, W, A, B any](fa Writer[W, A], f FCT) Writer[W, B] {
|
||||||
@@ -53,32 +53,32 @@ func Map[W any, FCT ~func(A) B, A, B any](f FCT) func(Writer[W, A]) Writer[W, B]
|
|||||||
return G.Map[Writer[W, B], Writer[W, A]](f)
|
return G.Map[Writer[W, B], Writer[W, A]](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChain[FCT ~func(A) Writer[W, B], W, A, B any](fa Writer[W, A], fct FCT) Writer[W, B] {
|
func MonadChain[FCT ~func(A) Writer[W, B], W, A, B any](s SG.Semigroup[W], fa Writer[W, A], fct FCT) Writer[W, B] {
|
||||||
return G.MonadChain[Writer[W, B], Writer[W, A], FCT](fa, fct)
|
return G.MonadChain[Writer[W, B], Writer[W, A], FCT](s, fa, fct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chain[A, B, W any](fa func(A) Writer[W, B]) func(Writer[W, A]) Writer[W, B] {
|
func Chain[A, B, W any](s SG.Semigroup[W], fa func(A) Writer[W, B]) func(Writer[W, A]) Writer[W, B] {
|
||||||
return G.Chain[Writer[W, B], Writer[W, A], func(A) Writer[W, B]](fa)
|
return G.Chain[Writer[W, B], Writer[W, A], func(A) Writer[W, B]](s, fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[B, A, W any](fab Writer[W, func(A) B], fa Writer[W, A]) Writer[W, B] {
|
func MonadAp[B, A, W any](s SG.Semigroup[W], fab Writer[W, func(A) B], fa Writer[W, A]) Writer[W, B] {
|
||||||
return G.MonadAp[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](fab, fa)
|
return G.MonadAp[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](s, fab, fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ap[B, A, W any](fa Writer[W, A]) func(Writer[W, func(A) B]) Writer[W, B] {
|
func Ap[B, A, W any](s SG.Semigroup[W], fa Writer[W, A]) func(Writer[W, func(A) B]) Writer[W, B] {
|
||||||
return G.Ap[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](fa)
|
return G.Ap[Writer[W, B], Writer[W, func(A) B], Writer[W, A]](s, fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](fa Writer[W, A], fct FCT) Writer[W, A] {
|
func MonadChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](s SG.Semigroup[W], fa Writer[W, A], fct FCT) Writer[W, A] {
|
||||||
return G.MonadChainFirst[Writer[W, B], Writer[W, A], FCT](fa, fct)
|
return G.MonadChainFirst[Writer[W, B], Writer[W, A], FCT](s, fa, fct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](fct FCT) func(Writer[W, A]) Writer[W, A] {
|
func ChainFirst[FCT ~func(A) Writer[W, B], W, A, B any](s SG.Semigroup[W], fct FCT) func(Writer[W, A]) Writer[W, A] {
|
||||||
return G.ChainFirst[Writer[W, B], Writer[W, A], FCT](fct)
|
return G.ChainFirst[Writer[W, B], Writer[W, A], FCT](s, fct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flatten[W, A any](mma Writer[W, Writer[W, A]]) Writer[W, A] {
|
func Flatten[W, A any](s SG.Semigroup[W], mma Writer[W, Writer[W, A]]) Writer[W, A] {
|
||||||
return G.Flatten[Writer[W, Writer[W, A]], Writer[W, A]](mma)
|
return G.Flatten[Writer[W, Writer[W, A]], Writer[W, A]](s, mma)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute extracts the accumulator
|
// Execute extracts the accumulator
|
||||||
@@ -102,13 +102,13 @@ func Censor[A any, FCT ~func(W) W, W any](f FCT) func(Writer[W, A]) Writer[W, A]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MonadListens projects a value from modifications made to the accumulator during an action
|
// MonadListens projects a value from modifications made to the accumulator during an action
|
||||||
func MonadListens[A any, FCT ~func(W) B, W, B any](fa Writer[W, A], f FCT) Writer[W, T.Tuple2[A, B]] {
|
func MonadListens[A any, FCT ~func(W) B, W, B any](fa Writer[W, A], f FCT) Writer[W, P.Pair[A, B]] {
|
||||||
return G.MonadListens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](fa, f)
|
return G.MonadListens[Writer[W, A], Writer[W, P.Pair[A, B]]](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listens projects a value from modifications made to the accumulator during an action
|
// Listens projects a value from modifications made to the accumulator during an action
|
||||||
func Listens[A any, FCT ~func(W) B, W, B any](f FCT) func(Writer[W, A]) Writer[W, T.Tuple2[A, B]] {
|
func Listens[A any, FCT ~func(W) B, W, B any](f FCT) func(Writer[W, A]) Writer[W, P.Pair[A, B]] {
|
||||||
return G.Listens[Writer[W, A], Writer[W, T.Tuple2[A, B]]](f)
|
return G.Listens[Writer[W, A], Writer[W, P.Pair[A, B]]](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFlap[W, B, A any](fab Writer[W, func(A) B], a A) Writer[W, B] {
|
func MonadFlap[W, B, A any](fab Writer[W, func(A) B], a A) Writer[W, B] {
|
||||||
|
@@ -20,24 +20,22 @@ import (
|
|||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
A "github.com/IBM/fp-go/array"
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
P "github.com/IBM/fp-go/pair"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func doubleAndLog(data int) Writer[[]string, int] {
|
func doubleAndLog(data int) Writer[[]string, int] {
|
||||||
return func() T.Tuple3[int, []string, S.Semigroup[[]string]] {
|
return func() P.Pair[int, []string] {
|
||||||
result := data * 2
|
result := data * 2
|
||||||
return T.MakeTuple3(result, A.Of(fmt.Sprintf("Doubled %d -> %d", data, result)), sg)
|
return P.MakePair(result, A.Of(fmt.Sprintf("Doubled %d -> %d", data, result)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleWriter_logging() {
|
func ExampleWriter_logging() {
|
||||||
|
|
||||||
res := F.Pipe4(
|
res := F.Pipe3(
|
||||||
10,
|
Of[int](monoid, 10),
|
||||||
Of[int](monoid),
|
Chain(sg, doubleAndLog),
|
||||||
Chain(doubleAndLog),
|
Chain(sg, doubleAndLog),
|
||||||
Chain(doubleAndLog),
|
|
||||||
Execute[[]string, int],
|
Execute[[]string, int],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user