mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: use tag to discriminate values
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
65
either/core.go
Normal file
65
either/core.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package either
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type EitherTag string
|
||||||
|
|
||||||
|
const (
|
||||||
|
leftTag = "Left"
|
||||||
|
rightTag = "Right"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Either defines a data structure that logically holds either an E or an A. The tag discriminates the cases
|
||||||
|
type Either[E, A any] struct {
|
||||||
|
tag EitherTag `default:"Left"`
|
||||||
|
left E
|
||||||
|
right A
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints some debug info for the object
|
||||||
|
func (s Either[E, A]) String() string {
|
||||||
|
switch s.tag {
|
||||||
|
case leftTag:
|
||||||
|
return fmt.Sprintf("%s[%T, %T](%v)", s.tag, s.left, s.right, s.left)
|
||||||
|
case rightTag:
|
||||||
|
return fmt.Sprintf("%s[%T, %T](%v)", s.tag, s.left, s.right, s.right)
|
||||||
|
}
|
||||||
|
return "Invalid"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format prints some debug info for the object
|
||||||
|
func (s Either[E, A]) Format(f fmt.State, c rune) {
|
||||||
|
switch c {
|
||||||
|
case 's':
|
||||||
|
fmt.Fprint(f, s.String())
|
||||||
|
default:
|
||||||
|
fmt.Fprint(f, s.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLeft[E, A any](val Either[E, A]) bool {
|
||||||
|
return val.tag == leftTag
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRight[E, A any](val Either[E, A]) bool {
|
||||||
|
return val.tag == rightTag
|
||||||
|
}
|
||||||
|
|
||||||
|
func Left[E, A any](value E) Either[E, A] {
|
||||||
|
return Either[E, A]{tag: leftTag, left: value}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Right[E, A any](value A) Either[E, A] {
|
||||||
|
return Either[E, A]{tag: rightTag, right: value}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadFold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B {
|
||||||
|
if IsLeft(ma) {
|
||||||
|
return onLeft(ma.left)
|
||||||
|
}
|
||||||
|
return onRight(ma.right)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unwrap[E, A any](ma Either[E, A]) (A, E) {
|
||||||
|
return ma.right, ma.left
|
||||||
|
}
|
@@ -19,8 +19,8 @@ func FromIO[E, A any](f func() A) Either[E, A] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[E, A, B any](fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B] {
|
func MonadAp[E, A, B any](fab Either[E, func(a A) B], fa Either[E, A]) Either[E, B] {
|
||||||
return fold(fab, Left[E, B], func(ab func(A) B) Either[E, B] {
|
return MonadFold(fab, Left[E, B], func(ab func(A) B) Either[E, B] {
|
||||||
return fold(fa, Left[E, B], F.Flow2(ab, Right[E, B]))
|
return MonadFold(fa, Left[E, B], F.Flow2(ab, Right[E, B]))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ func MonadMap[E, A, B any](fa Either[E, A], f func(a A) B) Either[E, B] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonadBiMap[E1, E2, A, B any](fa Either[E1, A], f func(E1) E2, g func(a A) B) Either[E2, B] {
|
func MonadBiMap[E1, E2, A, B any](fa Either[E1, A], f func(E1) E2, g func(a A) B) Either[E2, B] {
|
||||||
return fold(fa, F.Flow2(f, Left[E2, B]), F.Flow2(g, Right[E2, B]))
|
return MonadFold(fa, F.Flow2(f, Left[E2, B]), F.Flow2(g, Right[E2, B]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
||||||
@@ -50,7 +50,7 @@ func MapTo[E, A, B any](b B) func(Either[E, A]) Either[E, B] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonadMapLeft[E, A, B any](fa Either[E, A], f func(E) B) Either[B, A] {
|
func MonadMapLeft[E, A, B any](fa Either[E, A], f func(E) B) Either[B, A] {
|
||||||
return fold(fa, F.Flow2(f, Left[B, A]), Right[B, A])
|
return MonadFold(fa, F.Flow2(f, Left[B, A]), Right[B, A])
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[E, A, B any](f func(a A) B) func(fa Either[E, A]) Either[E, B] {
|
func Map[E, A, B any](f func(a A) B) func(fa Either[E, A]) Either[E, B] {
|
||||||
@@ -62,7 +62,7 @@ func MapLeft[E, A, B any](f func(E) B) func(fa Either[E, A]) Either[B, A] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] {
|
func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] {
|
||||||
return fold(fa, Left[E, B], f)
|
return MonadFold(fa, Left[E, B], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainFirst[E, A, B any](ma Either[E, A], f func(a A) Either[E, B]) Either[E, A] {
|
func MonadChainFirst[E, A, B any](ma Either[E, A], f func(a A) Either[E, B]) Either[E, A] {
|
||||||
@@ -147,7 +147,7 @@ func FromError[A any](f func(a A) error) func(A) Either[error, A] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ToError[A any](e Either[error, A]) error {
|
func ToError[A any](e Either[error, A]) error {
|
||||||
return fold(e, E.IdentityError, F.Constant1[A, error](nil))
|
return MonadFold(e, E.IdentityError, F.Constant1[A, error](nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Eitherize0G[GA ~func() (R, error), GB ~func() Either[error, R], R any](f GA) GB {
|
func Eitherize0G[GA ~func() (R, error), GB ~func() Either[error, R], R any](f GA) GB {
|
||||||
@@ -256,13 +256,9 @@ func Uneitherize4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) Either[error, R]
|
|||||||
return Uneitherize4G[func(T1, T2, T3, T4) Either[error, R], func(T1, T2, T3, T4) (R, error)](f)
|
return Uneitherize4G[func(T1, T2, T3, T4) Either[error, R], func(T1, T2, T3, T4) (R, error)](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B {
|
|
||||||
return fold(ma, onLeft, onRight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Fold[E, A, B any](onLeft func(E) B, onRight func(A) B) func(Either[E, A]) B {
|
func Fold[E, A, B any](onLeft func(E) B, onRight func(A) B) func(Either[E, A]) B {
|
||||||
return func(ma Either[E, A]) B {
|
return func(ma Either[E, A]) B {
|
||||||
return fold(ma, onLeft, onRight)
|
return MonadFold(ma, onLeft, onRight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,17 +317,17 @@ func Memoize[E, A any](val Either[E, A]) Either[E, A] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R] {
|
func MonadSequence2[E, T1, T2, R any](e1 Either[E, T1], e2 Either[E, T2], f func(T1, T2) Either[E, R]) Either[E, R] {
|
||||||
return fold(e1, Left[E, R], func(t1 T1) Either[E, R] {
|
return MonadFold(e1, Left[E, R], func(t1 T1) Either[E, R] {
|
||||||
return fold(e2, Left[E, R], func(t2 T2) Either[E, R] {
|
return MonadFold(e2, Left[E, R], func(t2 T2) Either[E, R] {
|
||||||
return f(t1, t2)
|
return f(t1, t2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], f func(T1, T2, T3) Either[E, R]) Either[E, R] {
|
func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3 Either[E, T3], f func(T1, T2, T3) Either[E, R]) Either[E, R] {
|
||||||
return fold(e1, Left[E, R], func(t1 T1) Either[E, R] {
|
return MonadFold(e1, Left[E, R], func(t1 T1) Either[E, R] {
|
||||||
return fold(e2, Left[E, R], func(t2 T2) Either[E, R] {
|
return MonadFold(e2, Left[E, R], func(t2 T2) Either[E, R] {
|
||||||
return fold(e3, Left[E, R], func(t3 T3) Either[E, R] {
|
return MonadFold(e3, Left[E, R], func(t3 T3) Either[E, R] {
|
||||||
return f(t1, t2, t3)
|
return f(t1, t2, t3)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -340,5 +336,5 @@ func MonadSequence3[E, T1, T2, T3, R any](e1 Either[E, T1], e2 Either[E, T2], e3
|
|||||||
|
|
||||||
// Swap changes the order of type parameters
|
// Swap changes the order of type parameters
|
||||||
func Swap[E, A any](val Either[E, A]) Either[A, E] {
|
func Swap[E, A any](val Either[E, A]) Either[A, E] {
|
||||||
return fold(val, Right[A, E], Left[A, E])
|
return MonadFold(val, Right[A, E], Left[A, E])
|
||||||
}
|
}
|
||||||
|
@@ -1,55 +0,0 @@
|
|||||||
package either
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type EitherTag int
|
|
||||||
|
|
||||||
const (
|
|
||||||
LeftTag EitherTag = iota
|
|
||||||
RightTag
|
|
||||||
)
|
|
||||||
|
|
||||||
// Either defines a data structure that logically holds either an E or an A. The tag discriminates the cases
|
|
||||||
type Either[E, A any] struct {
|
|
||||||
Tag EitherTag
|
|
||||||
Left E
|
|
||||||
Right A
|
|
||||||
}
|
|
||||||
|
|
||||||
// String prints some debug info for the object
|
|
||||||
func (s Either[E, A]) String() string {
|
|
||||||
switch s.Tag {
|
|
||||||
case LeftTag:
|
|
||||||
return fmt.Sprintf("Left[%T, %T](%v)", s.Left, s.Right, s.Left)
|
|
||||||
case RightTag:
|
|
||||||
return fmt.Sprintf("Right[%T, %T](%v)", s.Left, s.Right, s.Right)
|
|
||||||
}
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsLeft[E, A any](val Either[E, A]) bool {
|
|
||||||
return val.Tag == LeftTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsRight[E, A any](val Either[E, A]) bool {
|
|
||||||
return val.Tag == RightTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func Left[E, A any](value E) Either[E, A] {
|
|
||||||
return Either[E, A]{Tag: LeftTag, Left: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Right[E, A any](value A) Either[E, A] {
|
|
||||||
return Either[E, A]{Tag: RightTag, Right: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B {
|
|
||||||
if IsLeft(ma) {
|
|
||||||
return onLeft(ma.Left)
|
|
||||||
}
|
|
||||||
return onRight(ma.Right)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Unwrap[E, A any](ma Either[E, A]) (A, E) {
|
|
||||||
return ma.Right, ma.Left
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
//go:build disabled
|
|
||||||
|
|
||||||
package either
|
|
||||||
|
|
||||||
// Either will either be E or A
|
|
||||||
type Either[E, A any] interface {
|
|
||||||
fmt.Stringer
|
|
||||||
}
|
|
||||||
|
|
||||||
type left[E any] struct {
|
|
||||||
e E
|
|
||||||
}
|
|
||||||
|
|
||||||
func (left[E]) IsLeft() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type right[A any] struct {
|
|
||||||
a A
|
|
||||||
}
|
|
||||||
|
|
||||||
func (right[A]) IsLeft() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l left[E]) String() string {
|
|
||||||
return fmt.Sprintf("Left[%v]", l.e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r right[A]) String() string {
|
|
||||||
return fmt.Sprintf("Right[%v]", r.a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsLeft[E, A any](val Either[E, A]) bool {
|
|
||||||
switch any(val).(type) {
|
|
||||||
case left[E]:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsRight[E, A any](val Either[E, A]) bool {
|
|
||||||
return !IsLeft(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Left[E, A any](value E) Either[E, A] {
|
|
||||||
return left[E]{e: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Right[E, A any](value A) Either[E, A] {
|
|
||||||
return right[A]{a: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func fold[E, A, B any](ma Either[E, A], onLeft func(e E) B, onRight func(a A) B) B {
|
|
||||||
if IsLeft(ma) {
|
|
||||||
return onLeft(ma.(left[E]).e)
|
|
||||||
}
|
|
||||||
return onRight(ma.(right[A]).a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Unwrap[E, A any](ma Either[E, A]) (A, E) {
|
|
||||||
if IsLeft(ma) {
|
|
||||||
var a A
|
|
||||||
return a, ma.(left[E]).e
|
|
||||||
}
|
|
||||||
var E e
|
|
||||||
return ma.(right[A]).a, e
|
|
||||||
}
|
|
@@ -14,7 +14,7 @@ func WithResource[E, R, A any](onCreate func() Either[E, R], onRelease func(R) E
|
|||||||
res := f(r)
|
res := f(r)
|
||||||
released := onRelease(r)
|
released := onRelease(r)
|
||||||
// handle the errors
|
// handle the errors
|
||||||
return fold(
|
return MonadFold(
|
||||||
res,
|
res,
|
||||||
Left[E, A],
|
Left[E, A],
|
||||||
func(a A) Either[E, A] {
|
func(a A) Either[E, A] {
|
||||||
|
@@ -21,7 +21,7 @@ func traverse[E, A, B, HKTA, HKTB, HKTRB any](
|
|||||||
right := F.Bind2nd(_map, Right[E, B])
|
right := F.Bind2nd(_map, Right[E, B])
|
||||||
|
|
||||||
return func(ta Either[E, A], f func(A) HKTB) HKTRB {
|
return func(ta Either[E, A], f func(A) HKTB) HKTRB {
|
||||||
return fold(ta,
|
return MonadFold(ta,
|
||||||
left,
|
left,
|
||||||
F.Flow2(f, right),
|
F.Flow2(f, right),
|
||||||
)
|
)
|
||||||
|
93
option/core.go
Normal file
93
option/core.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package option
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OptionTag string
|
||||||
|
|
||||||
|
const (
|
||||||
|
noneTag = "None"
|
||||||
|
someTag = "Some"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
jsonNull = []byte("null")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option defines a data structure that logically holds a value or not
|
||||||
|
type Option[A any] struct {
|
||||||
|
tag OptionTag `default:"None"`
|
||||||
|
value A
|
||||||
|
}
|
||||||
|
|
||||||
|
// String prints some debug info for the object
|
||||||
|
func (s Option[A]) String() string {
|
||||||
|
switch s.tag {
|
||||||
|
case noneTag:
|
||||||
|
return fmt.Sprintf("%s[%T]", s.tag, s.value)
|
||||||
|
case someTag:
|
||||||
|
return fmt.Sprintf("%s[%T](%v)", s.tag, s.value, s.value)
|
||||||
|
}
|
||||||
|
return "Invalid"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format prints some debug info for the object
|
||||||
|
func (s Option[A]) Format(f fmt.State, c rune) {
|
||||||
|
switch c {
|
||||||
|
case 's':
|
||||||
|
fmt.Fprint(f, s.String())
|
||||||
|
default:
|
||||||
|
fmt.Fprint(f, s.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Option[A]) MarshalJSON() ([]byte, error) {
|
||||||
|
if s.tag == noneTag {
|
||||||
|
return jsonNull, nil
|
||||||
|
}
|
||||||
|
return json.Marshal(s.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Option[A]) UnmarshalJSON(data []byte) error {
|
||||||
|
// decode the value
|
||||||
|
if bytes.Equal(data, jsonNull) {
|
||||||
|
s.tag = noneTag
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
s.tag = someTag
|
||||||
|
return json.Unmarshal(data, &s.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsNone[T any](val Option[T]) bool {
|
||||||
|
return val.tag == noneTag
|
||||||
|
}
|
||||||
|
|
||||||
|
func Some[T any](value T) Option[T] {
|
||||||
|
return Option[T]{tag: someTag, value: value}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Of[T any](value T) Option[T] {
|
||||||
|
return Some(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func None[T any]() Option[T] {
|
||||||
|
return Option[T]{tag: noneTag}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsSome[T any](val Option[T]) bool {
|
||||||
|
return val.tag == someTag
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadFold[A, B any](ma Option[A], onNone func() B, onSome func(A) B) B {
|
||||||
|
if IsNone(ma) {
|
||||||
|
return onNone()
|
||||||
|
}
|
||||||
|
return onSome(ma.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Unwrap[A any](ma Option[A]) (A, bool) {
|
||||||
|
return ma.value, ma.tag == someTag
|
||||||
|
}
|
@@ -1,58 +0,0 @@
|
|||||||
package option
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type OptionTag int
|
|
||||||
|
|
||||||
const (
|
|
||||||
NoneTag OptionTag = iota
|
|
||||||
SomeTag
|
|
||||||
)
|
|
||||||
|
|
||||||
// Option defines a data structure that logically holds a value or not
|
|
||||||
type Option[A any] struct {
|
|
||||||
Tag OptionTag
|
|
||||||
Value A
|
|
||||||
}
|
|
||||||
|
|
||||||
// String prints some debug info for the object
|
|
||||||
func (s Option[A]) String() string {
|
|
||||||
switch s.Tag {
|
|
||||||
case NoneTag:
|
|
||||||
return fmt.Sprintf("None[%T]", s.Value)
|
|
||||||
case SomeTag:
|
|
||||||
return fmt.Sprintf("Some[%T](%v)", s.Value, s.Value)
|
|
||||||
}
|
|
||||||
return "Invalid"
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsNone[T any](val Option[T]) bool {
|
|
||||||
return val.Tag == NoneTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func Some[T any](value T) Option[T] {
|
|
||||||
return Option[T]{Tag: SomeTag, Value: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Of[T any](value T) Option[T] {
|
|
||||||
return Some(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func None[T any]() Option[T] {
|
|
||||||
return Option[T]{Tag: NoneTag}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsSome[T any](val Option[T]) bool {
|
|
||||||
return val.Tag == SomeTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadFold[A, B any](ma Option[A], onNone func() B, onSome func(A) B) B {
|
|
||||||
if IsNone(ma) {
|
|
||||||
return onNone()
|
|
||||||
}
|
|
||||||
return onSome(ma.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Unwrap[A any](ma Option[A]) (A, bool) {
|
|
||||||
return ma.Value, ma.Tag == SomeTag
|
|
||||||
}
|
|
@@ -1,61 +0,0 @@
|
|||||||
//go:build disabled
|
|
||||||
|
|
||||||
package option
|
|
||||||
|
|
||||||
// Option will be of type T or None
|
|
||||||
type Option[T any] interface {
|
|
||||||
fmt.Stringer
|
|
||||||
}
|
|
||||||
|
|
||||||
type none struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var const_none = none{}
|
|
||||||
|
|
||||||
func (none) String() string {
|
|
||||||
return "None"
|
|
||||||
}
|
|
||||||
|
|
||||||
type some[T any] struct {
|
|
||||||
v T
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s some[T]) String() string {
|
|
||||||
return fmt.Sprintf("Some[%v]", s.v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsNone[T any](val Option[T]) bool {
|
|
||||||
return val == const_none
|
|
||||||
}
|
|
||||||
|
|
||||||
func Some[T any](value T) Option[T] {
|
|
||||||
return some[T]{v: value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Of[T any](value T) Option[T] {
|
|
||||||
return Some(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func None[T any]() Option[T] {
|
|
||||||
return const_none
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsSome[T any](val Option[T]) bool {
|
|
||||||
return !IsNone(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadFold[A, B any](ma Option[A], onNone func() B, onSome func(A) B) B {
|
|
||||||
if IsNone(ma) {
|
|
||||||
return onNone()
|
|
||||||
}
|
|
||||||
return onSome(ma.(some[A]).v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Unwrap[A any](a A) func(Option[A]) (A, bool) {
|
|
||||||
return func(ma Option[A]) (A, bool) {
|
|
||||||
if IsNone(ma) {
|
|
||||||
return a, false
|
|
||||||
}
|
|
||||||
return ma.(some[A]).v, true
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user