github.com/MetalBlockchain/metalgo@v1.11.9/utils/maybe/maybe.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package maybe
     5  
     6  import "fmt"
     7  
     8  // Maybe T = Some T | Nothing.
     9  // A data wrapper that allows values to be something [Some T] or nothing [Nothing].
    10  // Invariant: If [hasValue] is false, then [value] is the zero value of type T.
    11  // Maybe is used to wrap types:
    12  // * That can't be represented by nil.
    13  // * That use nil as a valid value instead of an indicator of a missing value.
    14  // For more info see https://en.wikipedia.org/wiki/Option_type
    15  type Maybe[T any] struct {
    16  	hasValue bool
    17  	// If [hasValue] is false, [value] is the zero value of type T.
    18  	value T
    19  }
    20  
    21  // Some returns a new Maybe[T] with the value val.
    22  // If m.IsNothing(), returns the zero value of type T.
    23  func Some[T any](val T) Maybe[T] {
    24  	return Maybe[T]{
    25  		value:    val,
    26  		hasValue: true,
    27  	}
    28  }
    29  
    30  // Nothing returns a new Maybe[T] with no value.
    31  func Nothing[T any]() Maybe[T] {
    32  	return Maybe[T]{}
    33  }
    34  
    35  // IsNothing returns false iff [m] has a value.
    36  func (m Maybe[T]) IsNothing() bool {
    37  	return !m.hasValue
    38  }
    39  
    40  // HasValue returns true iff [m] has a value.
    41  func (m Maybe[T]) HasValue() bool {
    42  	return m.hasValue
    43  }
    44  
    45  // Value returns the value of [m].
    46  func (m Maybe[T]) Value() T {
    47  	return m.value
    48  }
    49  
    50  func (m Maybe[T]) String() string {
    51  	if !m.hasValue {
    52  		return fmt.Sprintf("Nothing[%T]", m.value)
    53  	}
    54  	return fmt.Sprintf("Some[%T]{%v}", m.value, m.value)
    55  }
    56  
    57  // Bind returns Nothing iff [m] is Nothing.
    58  // Otherwise applies [f] to the value of [m] and returns the result as a Some.
    59  func Bind[T, U any](m Maybe[T], f func(T) U) Maybe[U] {
    60  	if m.IsNothing() {
    61  		return Nothing[U]()
    62  	}
    63  	return Some(f(m.Value()))
    64  }
    65  
    66  // Equal returns true if both m1 and m2 are nothing or have the same value according to [equalFunc].
    67  func Equal[T any](m1 Maybe[T], m2 Maybe[T], equalFunc func(T, T) bool) bool {
    68  	if m1.IsNothing() {
    69  		return m2.IsNothing()
    70  	}
    71  
    72  	if m2.IsNothing() {
    73  		return false
    74  	}
    75  	return equalFunc(m1.Value(), m2.Value())
    76  }