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 }