All files / src/instances Applicative.ts

100% Statements 35/35
100% Branches 5/5
100% Functions 1/1
100% Lines 35/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 811x             1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 2952x 2952x 2952x 2952x 1x           1x                     1x 4x 4x 4x 4x 4x           1x 1x 1x 1x 1x 1x 1x 1x             1x   1x             1x 1x  
import {
  Applicative as AP,
  Monoid,
  SemiApplicative as SA,
  Semigroup,
  SemiProduct as SP,
} from '@effect/typeclass'
import {Array, Function, pipe} from 'effect'
import {leaf} from '../tree/index.js'
import {type Tree, type TreeTypeLambda} from '../tree/types.js'
import {pair} from '#Pair'
import {imap, map} from './Covariant.js'
import {flatMap} from './Monad.js'
 
/**
 * Cartesian product of two trees.
 * @category instances
 * @function
 */
export const product: SA.SemiApplicative<TreeTypeLambda>['product'] =
  Function.dual(
    2,
    <A, B>(self: Tree<A>, that: Tree<B>): Tree<readonly [A, B]> =>
      pipe(
        self,
        flatMap(self => pipe(that, map(pair.withFirst(self)))),
      ),
  )
 
/**
 * @category instances
 * @function
 */
export const productMany = SP.productMany<TreeTypeLambda>(map, product)
 
/**
 * Compute the cartesian product of multiple trees into a single tree.
 * Returns a leaf node containing an empty array if the input is empty.
 * @param collection Cartesian product will be computed on this iterable of
 * trees.
 * @returns The tree that is the cartesian product of all given trees.
 * @category instances
 * @function
 */
export const productAll: AP.Applicative<TreeTypeLambda>['productAll'] = <A>(
  collection: Iterable<Tree<A>>,
) => {
  const [head, ...tail] = Array.fromIterable(collection)
  return head === undefined ? leaf<A[]>([]) : productMany(head, tail)
}
 
/**
 * Applicative instance for {@link Tree}.
 * @category instances
 */
export const Applicative: AP.Applicative<TreeTypeLambda> = {
  of: leaf,
  imap,
  map,
  product,
  productMany,
  productAll,
}
 
/**
 * Creates an `Semigroup` for a `Tree<A>` type, given a `Semigroup`
 * for the underlying type `A`.
 * @category instances
 */
export const getSemigroup: <A>(
  F: Semigroup.Semigroup<A>,
) => Semigroup.Semigroup<Tree<A>> = SA.getSemigroup(Applicative)
 
/**
 * Creates a `Monoid` for a `Tree<A>` type, given a `Monoid`
 * for the underlying type `A`. `empty` will be a `leaf(M.empty)`.
 * @category instances
 */
export const getMonoid: <A>(F: Monoid.Monoid<A>) => Monoid.Monoid<Tree<A>> =
  AP.getMonoid(Applicative)