Skip to content

Commit 41b792b

Browse files
authored
Merge pull request #11 from IBM/cleue-better-doc
fix: introduce stateless iterator
2 parents 8c58e8d + 1713de0 commit 41b792b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2076
-25
lines changed

array/array.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func Append[A any](as []A, a A) []A {
144144
}
145145

146146
func IsEmpty[A any](as []A) bool {
147-
return array.IsEmpty(as)
147+
return G.IsEmpty(as)
148148
}
149149

150150
func IsNonEmpty[A any](as []A) bool {
@@ -181,12 +181,11 @@ func Ap[B, A any](fa []A) func([]func(A) B) []B {
181181
}
182182

183183
func Match[A, B any](onEmpty func() B, onNonEmpty func([]A) B) func([]A) B {
184-
return func(as []A) B {
185-
if IsEmpty(as) {
186-
return onEmpty()
187-
}
188-
return onNonEmpty(as)
189-
}
184+
return G.Match[[]A](onEmpty, onNonEmpty)
185+
}
186+
187+
func MatchLeft[A, B any](onEmpty func() B, onNonEmpty func(A, []A) B) func([]A) B {
188+
return G.MatchLeft[[]A](onEmpty, onNonEmpty)
190189
}
191190

192191
func Tail[A any](as []A) O.Option[[]A] {

array/generic/array.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,25 @@ func MonadAp[BS ~[]B, ABS ~[]func(A) B, AS ~[]A, B, A any](fab ABS, fa AS) BS {
158158
func Ap[BS ~[]B, ABS ~[]func(A) B, AS ~[]A, B, A any](fa AS) func(ABS) BS {
159159
return F.Bind2nd(MonadAp[BS, ABS, AS], fa)
160160
}
161+
162+
func IsEmpty[AS ~[]A, A any](as AS) bool {
163+
return array.IsEmpty(as)
164+
}
165+
166+
func Match[AS ~[]A, A, B any](onEmpty func() B, onNonEmpty func(AS) B) func(AS) B {
167+
return func(as AS) B {
168+
if IsEmpty(as) {
169+
return onEmpty()
170+
}
171+
return onNonEmpty(as)
172+
}
173+
}
174+
175+
func MatchLeft[AS ~[]A, A, B any](onEmpty func() B, onNonEmpty func(A, AS) B) func(AS) B {
176+
return func(as AS) B {
177+
if IsEmpty(as) {
178+
return onEmpty()
179+
}
180+
return onNonEmpty(as[0], as[1:])
181+
}
182+
}

bounded/bounded.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) 2023 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package bounded
17+
18+
import (
19+
O "github.com/IBM/fp-go/ord"
20+
)
21+
22+
type Bounded[T any] interface {
23+
O.Ord[T]
24+
Top() T
25+
Bottom() T
26+
}
27+
28+
type bounded[T any] struct {
29+
c func(x, y T) int
30+
e func(x, y T) bool
31+
t T
32+
b T
33+
}
34+
35+
func (self bounded[T]) Equals(x, y T) bool {
36+
return self.e(x, y)
37+
}
38+
39+
func (self bounded[T]) Compare(x, y T) int {
40+
return self.c(x, y)
41+
}
42+
43+
func (self bounded[T]) Top() T {
44+
return self.t
45+
}
46+
47+
func (self bounded[T]) Bottom() T {
48+
return self.b
49+
}
50+
51+
// MakeBounded creates an instance of a bounded type
52+
func MakeBounded[T any](o O.Ord[T], t, b T) Bounded[T] {
53+
return bounded[T]{c: o.Compare, e: o.Equals, t: t, b: b}
54+
}
55+
56+
// Clamp returns a function that clamps against the bounds defined in the bounded type
57+
func Clamp[T any](b Bounded[T]) func(T) T {
58+
return O.Clamp[T](b)(b.Bottom(), b.Top())
59+
}
60+
61+
// Reverse reverses the ordering and swaps the bounds
62+
func Reverse[T any](b Bounded[T]) Bounded[T] {
63+
return MakeBounded(O.Reverse[T](b), b.Bottom(), b.Top())
64+
}

bytes/bytes.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ package bytes
1818
func ToString(a []byte) string {
1919
return string(a)
2020
}
21+
22+
func Size(as []byte) int {
23+
return len(as)
24+
}

context/readerioeither/cancel.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
G "github.com/IBM/fp-go/context/readerioeither/generic"
2020
)
2121

22-
// WithContext wraps an existing ReaderIOEither and performs a context check for cancellation before delegating
22+
// WithContext wraps an existing [ReaderIOEither] and performs a context check for cancellation before delegating
2323
func WithContext[A any](ma ReaderIOEither[A]) ReaderIOEither[A] {
2424
return G.WithContext(ma)
2525
}

context/readerioeither/data/file.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Carsten

context/readerioeither/eq.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
EQ "github.com/IBM/fp-go/eq"
2424
)
2525

26-
// Eq implements the equals predicate for values contained in the IOEither monad
26+
// Eq implements the equals predicate for values contained in the [ReaderIOEither] monad
2727
func Eq[A any](eq EQ.Eq[ET.Either[error, A]]) func(context.Context) EQ.Eq[ReaderIOEither[A]] {
2828
return G.Eq[ReaderIOEither[A]](eq)
2929
}

context/readerioeither/file/file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func Close[C io.Closer](c C) RIOE.ReaderIOEither[any] {
4848

4949
// ReadFile reads a file in the scope of a context
5050
func ReadFile(path string) RIOE.ReaderIOEither[[]byte] {
51-
return RIOE.WithResource[*os.File, []byte](Open(path), Close[*os.File])(func(r *os.File) RIOE.ReaderIOEither[[]byte] {
51+
return RIOE.WithResource[[]byte](Open(path), Close[*os.File])(func(r *os.File) RIOE.ReaderIOEither[[]byte] {
5252
return func(ctx context.Context) IOE.IOEither[error, []byte] {
5353
return IOE.MakeIO(func() ET.Either[error, []byte] {
5454
return file.ReadAll(ctx, r)

context/readerioeither/resource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
)
2121

2222
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
23-
func WithResource[R, A, ANY any](onCreate ReaderIOEither[R], onRelease func(R) ReaderIOEither[ANY]) func(func(R) ReaderIOEither[A]) ReaderIOEither[A] {
23+
func WithResource[A, R, ANY any](onCreate ReaderIOEither[R], onRelease func(R) ReaderIOEither[ANY]) func(func(R) ReaderIOEither[A]) ReaderIOEither[A] {
2424
// wraps the callback functions with a context check
2525
return G.WithResource[ReaderIOEither[A]](onCreate, onRelease)
2626
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2023 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package readerioeither
17+
18+
import (
19+
"context"
20+
"io"
21+
"os"
22+
23+
B "github.com/IBM/fp-go/bytes"
24+
F "github.com/IBM/fp-go/function"
25+
IO "github.com/IBM/fp-go/io"
26+
IOE "github.com/IBM/fp-go/ioeither"
27+
)
28+
29+
var (
30+
openFile = F.Flow3(
31+
IOE.Eitherize1(os.Open),
32+
FromIOEither[*os.File],
33+
ChainFirstIOK(F.Flow2(
34+
(*os.File).Name,
35+
IO.Logf[string]("Opened file [%s]"),
36+
)),
37+
)
38+
)
39+
40+
func closeFile(f *os.File) ReaderIOEither[string] {
41+
return F.Pipe1(
42+
TryCatch(func(_ context.Context) func() (string, error) {
43+
return func() (string, error) {
44+
return f.Name(), f.Close()
45+
}
46+
}),
47+
ChainFirstIOK(IO.Logf[string]("Closed file [%s]")),
48+
)
49+
}
50+
51+
func ExampleWithResource() {
52+
53+
stringReader := WithResource[string](openFile("data/file.txt"), closeFile)
54+
55+
rdr := stringReader(func(f *os.File) ReaderIOEither[string] {
56+
return F.Pipe2(
57+
TryCatch(func(_ context.Context) func() ([]byte, error) {
58+
return func() ([]byte, error) {
59+
return io.ReadAll(f)
60+
}
61+
}),
62+
ChainFirstIOK(F.Flow2(
63+
B.Size,
64+
IO.Logf[int]("Read content of length [%d]"),
65+
)),
66+
Map(B.ToString),
67+
)
68+
})
69+
70+
contentIOE := F.Pipe2(
71+
context.Background(),
72+
rdr,
73+
IOE.ChainFirstIOK[error](IO.Printf[string]("Content: %s")),
74+
)
75+
76+
contentIOE()
77+
78+
// Output: Content: Carsten
79+
}

context/readerioeither/type.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ import (
2121
RE "github.com/IBM/fp-go/readerioeither"
2222
)
2323

24-
// ReaderIOEither is a specialization of the Reader monad for the typical golang scenario
24+
// ReaderIOEither is a specialization of the [RE.ReaderIOEither] monad for the typical golang scenario in which the
25+
// left value is an [error] and the context is a [context.Context]
2526
type ReaderIOEither[A any] RE.ReaderIOEither[context.Context, error, A]

erasure/erasure.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2023 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package erasure
17+
18+
import (
19+
F "github.com/IBM/fp-go/function"
20+
)
21+
22+
// Erase converts a variable of type T to an any by returning a pointer to that variable
23+
func Erase[T any](t T) any {
24+
return &t
25+
}
26+
27+
// Unerase converts an erased variable back to its original value
28+
func Unerase[T any](t any) T {
29+
return *t.(*T)
30+
}
31+
32+
// Erase0 converts a type safe function into an erased function
33+
func Erase0[T1 any](f func() T1) func() any {
34+
return F.Nullary2(f, Erase[T1])
35+
}
36+
37+
// Erase1 converts a type safe function into an erased function
38+
func Erase1[T1, T2 any](f func(T1) T2) func(any) any {
39+
return F.Flow3(
40+
Unerase[T1],
41+
f,
42+
Erase[T2],
43+
)
44+
}
45+
46+
// Erase2 converts a type safe function into an erased function
47+
func Erase2[T1, T2, T3 any](f func(T1, T2) T3) func(any, any) any {
48+
return func(t1, t2 any) any {
49+
return Erase(f(Unerase[T1](t1), Unerase[T2](t2)))
50+
}
51+
}

erasure/erasure_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2023 IBM Corp.
2+
// All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package erasure
17+
18+
import (
19+
"fmt"
20+
"strings"
21+
"testing"
22+
23+
E "github.com/IBM/fp-go/either"
24+
F "github.com/IBM/fp-go/function"
25+
)
26+
27+
func TestEither(t *testing.T) {
28+
29+
e1 := F.Pipe3(
30+
E.Of[error](Erase("Carsten")),
31+
E.Map[error](Erase1(strings.ToUpper)),
32+
E.GetOrElse(func(e error) any {
33+
return Erase("Error")
34+
}),
35+
Unerase[string],
36+
)
37+
38+
fmt.Println(e1)
39+
}

0 commit comments

Comments
 (0)