Skip to content

Commit 8971c4c

Browse files
committed
fn: add operations to Result API
1 parent 5faad77 commit 8971c4c

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

fn/result.go

+35-4
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,37 @@ func (r Result[T]) IsErr() bool {
6464
return r.IsRight()
6565
}
6666

67-
// Map applies a function to the success value if it exists.
67+
// Map applies an endomorphic function to the success value if it exists.
68+
//
69+
// Deprecated: Use MapOk instead.
6870
func (r Result[T]) Map(f func(T) T) Result[T] {
6971
return Result[T]{
7072
MapLeft[T, error](f)(r.Either),
7173
}
7274
}
7375

74-
// MapErr applies a function to the error value if it exists.
76+
// MapOk applies an endomorphic function to the success value if it exists.
77+
func (r Result[T]) MapOk(f func(T) T) Result[T] {
78+
return Result[T]{
79+
MapLeft[T, error](f)(r.Either),
80+
}
81+
}
82+
83+
// MapErr applies an endomorphic function to the error value if it exists.
7584
func (r Result[T]) MapErr(f func(error) error) Result[T] {
7685
return Result[T]{
7786
MapRight[T](f)(r.Either),
7887
}
7988
}
8089

90+
// MapOk applies a non-endomorphic function to the success value if it exists
91+
// and returns a Result of the new type.
92+
func MapOk[A, B any](f func(A) B) func(Result[A]) Result[B] {
93+
return func(r Result[A]) Result[B] {
94+
return Result[B]{MapLeft[A, error](f)(r.Either)}
95+
}
96+
}
97+
8198
// Option returns the success value as an Option.
8299
//
83100
// Deprecated: Use OkToSome instead.
@@ -137,8 +154,22 @@ func (r Result[T]) UnwrapOrFail(t *testing.T) T {
137154
return r.left
138155
}
139156

140-
// FlatMap applies a function that returns a Result to the success value if it
141-
// exists.
157+
// FlattenResult takes a nested Result and joins the two functor layers into
158+
// one.
159+
func FlattenResult[A any](r Result[Result[A]]) Result[A] {
160+
if r.IsErr() {
161+
return Err[A](r.right)
162+
}
163+
164+
if r.left.IsErr() {
165+
return Err[A](r.left.right)
166+
}
167+
168+
return r.left
169+
}
170+
171+
// FlatMap applies a kleisli endomorphic function that returns a Result to the
172+
// success value if it exists.
142173
func (r Result[T]) FlatMap(f func(T) Result[T]) Result[T] {
143174
if r.IsOk() {
144175
return r

fn/result_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package fn
22

33
import (
44
"errors"
5+
"fmt"
56
"testing"
7+
"testing/quick"
68

79
"github.com/stretchr/testify/require"
810
)
@@ -17,3 +19,29 @@ func TestOkToSome(t *testing.T) {
1719
t, Err[uint8](errors.New("err")).OkToSome(), None[uint8](),
1820
)
1921
}
22+
23+
func TestMapOk(t *testing.T) {
24+
inc := func(i int) int {
25+
return i + 1
26+
}
27+
f := func(i int) bool {
28+
ok := Ok(i)
29+
return MapOk(inc)(ok) == Ok(inc(i))
30+
}
31+
32+
require.NoError(t, quick.Check(f, nil))
33+
}
34+
35+
func TestFlattenResult(t *testing.T) {
36+
f := func(i int) bool {
37+
e := fmt.Errorf("error")
38+
39+
x := FlattenResult(Ok(Ok(i))) == Ok(i)
40+
y := FlattenResult(Ok(Err[int](e))) == Err[int](e)
41+
z := FlattenResult(Err[Result[int]](e)) == Err[int](e)
42+
43+
return x && y && z
44+
}
45+
46+
require.NoError(t, quick.Check(f, nil))
47+
}

0 commit comments

Comments
 (0)