signalis-eb/godot/addons/monads/option.gd
2025-06-10 21:54:23 -04:00

82 lines
1.9 KiB
GDScript

class_name Option extends RefCounted
static var Unit = Option.some(null)
static func some(value: Variant) -> Option:
return Some.new(value)
static var none: Option.None = None.new()
static func collect_some(options: Array[Option], ignore_none: bool = false) -> Option:
var result = []
for option in options:
if option.is_some():
result.push_back(option.unwrap())
elif not ignore_none:
return Option.none
return Option.some(result)
class Some extends Option:
var value: Variant
func _init(val: Variant) -> void:
value = val
func chain(fn: Callable) -> Option:
return fn.call(value)
func filter(fn: Callable) -> Option:
if fn.call(value): return self
else: return Option.none
func flatten() -> Option:
if value is Option:
return value.flatten()
else: return Option.some(value)
func map(fn: Callable) -> Option:
return Option.some(fn.call(value))
func is_some() -> bool:
return true
func is_none() -> bool:
return false
func or_default(_default_value: Variant) -> Variant:
return value
func or_else(_fn: Callable) -> Variant:
return value
func unwrap() -> Variant:
return value
class None extends Option:
func chain(_fn: Callable) -> Option:
return self
func filter(_f: Callable) -> Option:
return self
func flatten() -> Option:
return self
func map(_fn: Callable) -> Option:
return self
func is_some() -> bool:
return false
func is_none() -> bool:
return true
func or_default(default_value: Variant) -> Variant:
return default_value
func or_else(fn: Callable) -> Variant:
return fn.call()
func unwrap() -> Variant:
assert(false, "Called unwrap() on a None value")
return null