Packages

Ior (inclusive or) data structure implementation

Current section

Files

Jump to
ior src ior.gleam
Raw

src/ior.gleam

import gleam/option.{type Option, None, Some}
pub type Ior(left, right) {
Left(val: left)
Right(val: right)
Both(left: left, right: right)
}
pub fn fold(
ior: Ior(left, right),
case_left: fn(left) -> new,
case_right: fn(right) -> new,
case_both: fn(left, right) -> new,
) -> new {
case ior {
Left(val) -> case_left(val)
Right(val) -> case_right(val)
Both(left, right) -> case_both(left, right)
}
}
pub fn bimap(
ior: Ior(left, right),
left_map: fn(left) -> new_left,
right_map: fn(right) -> new_right,
) -> Ior(new_left, new_right) {
case ior {
Left(val) -> Left(left_map(val))
Right(val) -> Right(right_map(val))
Both(left, right) -> Both(left_map(left), right_map(right))
}
}
pub fn map(ior: Ior(left, right), f: fn(right) -> new) -> Ior(left, new) {
case ior {
Left(val) -> Left(val)
Right(val) -> Right(f(val))
Both(left, right) -> Both(left, f(right))
}
}
pub fn left_map(ior: Ior(left, right), f: fn(left) -> new) -> Ior(new, right) {
case ior {
Left(val) -> Left(f(val))
Right(val) -> Right(val)
Both(left, right) -> Both(f(left), right)
}
}
pub fn flat_map(
ior: Ior(left, right),
combine: fn(left, left) -> left,
f: fn(right) -> Ior(left, new),
) -> Ior(left, new) {
case ior {
Left(val) -> Left(val)
Right(val) -> f(val)
Both(left, right) ->
f(right)
|> left_map(combine(left, _))
}
}
pub fn combine(
ior: Ior(left, right),
ior2: Ior(left, right),
combine_left: fn(left, left) -> left,
combine_right: fn(right, right) -> right,
) -> Ior(left, right) {
let left_map = case
ior2
|> get_left
{
Some(val) -> combine_left(_, val)
None -> fn(val) { val }
}
let right_map = case
ior2
|> get_right
{
Some(val) -> combine_right(_, val)
None -> fn(val) { val }
}
ior
|> bimap(left_map, right_map)
}
pub fn put_left(ior: Ior(left, right), left: new) -> Ior(new, right) {
case ior {
Left(_) -> Left(left)
Right(val) -> Both(left, val)
Both(_, right) -> Both(left, right)
}
}
pub fn put_right(ior: Ior(left, right), right: new) -> Ior(left, new) {
case ior {
Left(value) -> Both(value, right)
Right(_) -> Right(right)
Both(left, _) -> Both(left, right)
}
}
pub fn is_left(ior: Ior(left, right)) -> Bool {
case ior {
Left(_) -> True
_ -> False
}
}
pub fn is_right(ior: Ior(left, right)) -> Bool {
case ior {
Right(_) -> True
_ -> False
}
}
pub fn is_both(ior: Ior(left, right)) -> Bool {
case ior {
Both(_, _) -> True
_ -> False
}
}
pub fn get_left(ior: Ior(left, right)) -> Option(left) {
case ior {
Left(val) -> Some(val)
Right(_) -> None
Both(left, _) -> Some(left)
}
}
pub fn get_right(ior: Ior(left, right)) -> Option(right) {
case ior {
Left(_) -> None
Right(val) -> Some(val)
Both(_, right) -> Some(right)
}
}
pub fn only_left(ior: Ior(left, right)) -> Option(left) {
case ior {
Left(val) -> Some(val)
_ -> None
}
}
pub fn only_right(ior: Ior(left, right)) -> Option(right) {
case ior {
Right(val) -> Some(val)
_ -> None
}
}
pub fn only_both(ior: Ior(left, right)) -> Option(#(left, right)) {
case ior {
Both(left, right) -> Some(#(left, right))
_ -> None
}
}
pub fn as_options(ior: Ior(left, right)) -> #(Option(left), Option(right)) {
case ior {
Left(val) -> #(Some(val), None)
Right(val) -> #(None, Some(val))
Both(left, right) -> #(Some(left), Some(right))
}
}
pub fn swap(ior: Ior(left, right)) -> Ior(right, left) {
case ior {
Left(val) -> Right(val)
Right(val) -> Left(val)
Both(left, right) -> Both(right, left)
}
}
pub fn exists(ior: Ior(left, right), predicate: fn(right) -> Bool) -> Bool {
case
ior
|> get_right
{
Some(val) -> predicate(val)
None -> False
}
}
pub fn for_all(ior: Ior(left, right), predicate: fn(right) -> Bool) -> Bool {
case
ior
|> get_right
{
Some(val) -> predicate(val)
None -> True
}
}
pub fn get_or_else(ior: Ior(left, right), default: right) -> right {
case
ior
|> get_right
{
Some(val) -> val
None -> default
}
}