import type * as P from "@principia/prelude";
import * as HKT from "@principia/prelude/HKT";
import type { Monoid } from "@principia/prelude/Monoid";
import { isNone } from "./guards";
import type { Option, URI, V } from "./model";
/*
* -------------------------------------------
* Foldable Option
* -------------------------------------------
*/
/**
* ```haskell
* reduce_ :: Foldable f => (f a, b, ((b, a) -> b)) -> b
* ```
*/
export const reduce_ = (fa: Option, b: B, f: (b: B, a: A) => B): B => (isNone(fa) ? b : f(b, fa.value));
/**
* ```haskell
* reduce :: Foldable f => (b, ((b, a) -> b)) -> f a -> b
* ```
*/
export const reduce = (b: B, f: (b: B, a: A) => B) => (fa: Option): B => reduce_(fa, b, f);
/**
* ```haskell
* reduceRight_ :: Foldable f => (f a, b, ((b, a) -> b)) -> b
* ```
*/
export const reduceRight_ = (fa: Option, b: B, f: (a: A, b: B) => B): B => (isNone(fa) ? b : f(fa.value, b));
/**
* ```haskell
* reduceRight :: Foldable f => (b, ((b, a) -> b)) -> f a -> b
* ```
*/
export const reduceRight = (b: B, f: (a: A, b: B) => B) => (fa: Option): B => reduceRight_(fa, b, f);
/**
* ```haskell
* foldMap_ :: (Foldable f, Monoid m) => Instance m b -> (f a, (a -> b)) -> b
* ```
*/
export const foldMap_ = (M: Monoid) => (fa: Option, f: (a: A) => M): M =>
isNone(fa) ? M.nat : f(fa.value);
/**
* ```haskell
* foldMap :: (Foldable f, Monoid m) => Instance m b -> (a -> b) -> f a -> b
* ```
*/
export const foldMap = (M: Monoid) => (f: (a: A) => M) => (fa: Option): M => foldMap_(M)(fa, f);
export const Foldable: P.Foldable<[URI], V> = HKT.instance({
reduce_,
reduceRight_,
foldMap_,
reduce,
reduceRight,
foldMap
});