import type { Semigroup } from "@principia/prelude/Semigroup";
import { fromCombine } from "@principia/prelude/Semigroup";
/*
* -------------------------------------------
* FreeSemigroup Model
* -------------------------------------------
*/
export interface Element {
readonly _tag: "Element";
readonly value: A;
}
export interface Combine {
readonly _tag: "Combine";
readonly left: FreeSemigroup;
readonly right: FreeSemigroup;
}
export type FreeSemigroup = Element | Combine;
/*
* -------------------------------------------
* FreeSemigroup Constructors
* -------------------------------------------
*/
/**
* @category Constructors
* @since 1.0.0
*/
export const combine = (left: FreeSemigroup, right: FreeSemigroup): FreeSemigroup => ({
_tag: "Combine",
left,
right
});
/**
* @category Constructors
* @since 1.0.0
*/
export const element = (a: A): FreeSemigroup => ({
_tag: "Element",
value: a
});
/*
* -------------------------------------------
* FreeSemigroup Destructors
* -------------------------------------------
*/
/**
* @category Destructors
* @since 1.0.0
*/
export const fold = (onOf: (value: A) => R, onConcat: (left: FreeSemigroup, right: FreeSemigroup) => R) => (
f: FreeSemigroup
): R => {
switch (f._tag) {
case "Element":
return onOf(f.value);
case "Combine":
return onConcat(f.left, f.right);
}
};
/*
* -------------------------------------------
* FreeSemigroup Instances
* -------------------------------------------
*/
/**
* @category Instances
* @since 1.0.0
*/
export const getSemigroup = (): Semigroup> => fromCombine(combine);