fn: add transpositions for Option and Result

This commit is contained in:
Keagan McClelland 2024-08-13 16:59:18 -07:00
parent 8971c4c3ae
commit 5dec35426c
No known key found for this signature in database
GPG Key ID: FA7E65C951F12439
4 changed files with 74 additions and 0 deletions

View File

@ -251,3 +251,15 @@ func (o Option[A]) SomeToOkf(errString string, args ...interface{}) Result[A] {
OptionToLeft[A, A, error](o, fmt.Errorf(errString, args...)),
}
}
// TransposeOptRes transposes the Option[Result[A]] into a Result[Option[A]].
// This has the effect of leaving an A value alone while inverting the Option
// and Result layers. If there is no internal A value, it will convert the
// non-success value to the proper one in the transposition.
func TransposeOptRes[A any](o Option[Result[A]]) Result[Option[A]] {
if o.IsNone() {
return Ok(None[A]())
}
return Result[Option[A]]{MapLeft[A, error](Some[A])(o.some.Either)}
}

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"testing"
"testing/quick"
"github.com/stretchr/testify/require"
)
@ -26,3 +27,27 @@ func TestSomeToOkf(t *testing.T) {
Err[uint8](fmt.Errorf(errStr)),
)
}
func TestPropTransposeOptResInverts(t *testing.T) {
f := func(i uint) bool {
var o Option[Result[uint]]
switch i % 3 {
case 0:
o = Some(Ok(i))
case 1:
o = Some(Errf[uint]("error"))
case 2:
o = None[Result[uint]]()
default:
return false
}
odd := TransposeOptRes(o) ==
TransposeOptRes(TransposeResOpt(TransposeOptRes(o)))
even := TransposeResOpt(TransposeOptRes(o)) == o
return odd && even
}
require.NoError(t, quick.Check(f, nil))
}

View File

@ -223,3 +223,15 @@ func AndThen2[A, B, C any](ra Result[A], rb Result[B],
})
})
}
// TransposeResOpt transposes the Result[Option[A]] into a Option[Result[A]].
// This has the effect of leaving an A value alone while inverting the Result
// and Option layers. If there is no internal A value, it will convert the
// non-success value to the proper one in the transposition.
func TransposeResOpt[A any](r Result[Option[A]]) Option[Result[A]] {
if r.IsErr() {
return Some(Err[A](r.right))
}
return MapOption(Ok[A])(r.left)
}

View File

@ -45,3 +45,28 @@ func TestFlattenResult(t *testing.T) {
require.NoError(t, quick.Check(f, nil))
}
func TestPropTransposeResOptInverts(t *testing.T) {
f := func(i uint) bool {
var r Result[Option[uint]]
switch i % 3 {
case 0:
r = Ok(Some(i))
case 1:
r = Ok(None[uint]())
case 2:
r = Errf[Option[uint]]("error")
default:
return false
}
odd := TransposeResOpt(TransposeOptRes(TransposeResOpt(r))) ==
TransposeResOpt(r)
even := TransposeOptRes(TransposeResOpt(r)) == r
return odd && even
}
require.NoError(t, quick.Check(f, nil))
}