Skip to main content Link Search Menu Expand Document (external link)

Array overview

Extensions to the Effect Array module providing predicates, indexed search, cardinality matching, indexed (un)grouping, sorted-iterator merging/difference, and cycle-aware unfolding.

Mental model

  • Type<A> is just ReadonlyArray<A>; functions never mutate the input.
  • All functions are curried, data-last — call as MArray.fn(arg)(self) or pipe(self, MArray.fn(arg)). They are not data-first/data-last dual.
  • Equality-based functions (e.g. {@link hasDuplicates}, {@link longestCommonSubArray}, {@link differenceSorted}) compare with Equal.equals. The *With variants take an explicit Equivalence.

Common tasks

  • Predicates: {@link hasLength}, {@link hasDuplicates}, {@link hasDuplicatesWith}
  • Search: {@link findAll}, {@link extractFirst}, {@link getFromEnd}, {@link longestCommonSubArray}
  • Pattern match: {@link match012}
  • Unsafe access: {@link unsafeGet}, {@link unsafeGetter}
  • Modify by position: {@link modifyHead}, {@link modifyInit}, {@link modifyTail}, {@link modifyLast}
  • Group / ungroup: {@link ungroup}, {@link groupByNum}, {@link groupBy}
  • Split: {@link splitAtFromRight}, {@link splitNonEmptyAtFromRight}
  • Map / reduce with short-circuit: {@link mapUnlessNone}, {@link mapUnlessLeft}, {@link reduceUnlessNone}, {@link reduceUnlessLeft}
  • Sorted operations: {@link mergeSorted}, {@link differenceSorted}
  • Construct: {@link unfold}, {@link unfoldNonEmpty}, {@link pad}
  • Format: {@link removeEmptyAndJoin}

Quickstart

Example (Common predicates and indexed search)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"
import * as MPredicate from "@parischap/effect-lib/MPredicate"

console.log(MArray.hasDuplicates([1, 2, 2, 3])) // true
console.log(pipe([1, 2, 3, 2], MArray.findAll(MPredicate.strictEquals(2)))) // [1, 3]

Table of contents


Constructors

unfold

Curried version of Array.unfold with optional cycle detection.

  • Without seedEquivalence, behaves like a curried Array.unfold: keep generating until f returns Option.none.
  • With seedEquivalence, every seed is recorded; if the same seed reappears, cycleSource is a some of the A produced the first time that seed was processed, allowing the caller to break the cycle.

Example (Unfold without cycle detection)

import { Option, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const result = pipe(
  0,
  MArray.unfold((n) => (n < 3 ? Option.some([n, n + 1] as const) : Option.none()))
)
console.log(result) // [0, 1, 2]

Signature

export declare const unfold: {
  <S, A>(f: (s: S) => Option.Option<MTypes.Pair<A, S>>): (s: S) => Array<A>
  <S, A>(
    f: (s: S, cycleSource: Option.Option<NoInfer<A>>) => Option.Option<MTypes.Pair<A, S>>,
    seedEquivalence: Equivalence.Equivalence<S>
  ): (s: S) => Array<A>
}

unfoldNonEmpty

Variant of {@link unfold} where each step always produces an A and optionally a next seed S, guaranteeing a non-empty result.

  • Use when at least one element must be produced.
  • Cycle detection works the same way as in {@link unfold}.

Example (Unfold a non-empty array)

import { Option, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const result = pipe(
  0,
  MArray.unfoldNonEmpty((n) => [n, n < 2 ? Option.some(n + 1) : Option.none()] as const)
)
console.log(result) // [0, 1, 2]

Signature

export declare const unfoldNonEmpty: {
  <S, A>(f: (s: S) => MTypes.Pair<A, Option.Option<S>>): (s: S) => MTypes.OverOne<A>
  <S, A>(
    f: (s: S, cycleSource: Option.Option<NoInfer<A>>) => MTypes.Pair<A, Option.Option<S>>,
    seedEquivalence: Equivalence.Equivalence<S>
  ): (s: S) => MTypes.OverOne<A>
}

Destructors

getter

Returns a function that retrieves the element at a given index from self, wrapped in an Option.

  • Use to precompute a getter once when the same array will be queried many times.
  • The returned function is curried for the index and returns Option.none for out-of-bounds accesses.

Example (Reusable safe getter)

import * as MArray from "@parischap/effect-lib/MArray"

const get = MArray.getter([1, 2, 3])
console.log(get(0)) // Some(1)
console.log(get(5)) // None

Signature

export declare const getter: <A>(self: Type<A>) => MTypes.OneArgFunction<number, Option.Option<A>>

mapUnlessLeft

Maps every element of self with f, returning Result.success of the mapped array if every call succeeds, or the first failure encountered.

  • Use when each step can produce a typed error.
  • Short-circuits on the first failure returned by f.

Example (Map with error handling)

import { Result, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const parseIntSafe = (s: string) => {
  const n = parseInt(s)
  return Number.isNaN(n) ? Result.fail(`Invalid number: ${s}`) : Result.succeed(n)
}

console.log(pipe(["1", "2", "3"], MArray.mapUnlessLeft(parseIntSafe))) // Success([1, 2, 3])
console.log(pipe(["1", "x", "3"], MArray.mapUnlessLeft(parseIntSafe))) // Failure('Invalid number: x')

Signature

export declare const mapUnlessLeft: <S extends MTypes.AnyReadonlyArray, B, C>(
  f: (a: Array.ReadonlyArray.Infer<S>, i: number) => Result.Result<B, C>
) => (self: S) => Result.Result<Array.ReadonlyArray.With<S, B>, C>

mapUnlessNone

Maps every element of self with f, returning Option.some of the mapped array if every call succeeds, or Option.none as soon as one call returns Option.none.

  • Use when every element must be mappable for the operation to make sense.
  • Short-circuits on the first Option.none returned by f.

Example (Map with possible failure)

import { Option, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const safeDiv = (x: number) => (x !== 0 ? Option.some(10 / x) : Option.none())

console.log(pipe([2, 5], MArray.mapUnlessNone(safeDiv))) // Some([5, 2])
console.log(pipe([2, 0, 5], MArray.mapUnlessNone(safeDiv))) // None

Signature

export declare const mapUnlessNone: <S extends MTypes.AnyReadonlyArray, B>(
  f: (a: Array.ReadonlyArray.Infer<S>, i: number) => Option.Option<B>
) => (self: S) => Option.Option<Array.ReadonlyArray.With<S, B>>

reduceUnlessLeft

Reduces self with f, returning Result.success of the final accumulator if every step succeeds, or the first failure encountered.

  • Use when reducing with a step that can produce a typed error.
  • Short-circuits on the first failure.

Example (Reduce with error handling)

import { Result, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const safeSum = (acc: number, x: string) => {
  const n = parseInt(x)
  return Number.isNaN(n) ? Result.fail(`Invalid: ${x}`) : Result.succeed(acc + n)
}

console.log(pipe(["1", "2", "3"], MArray.reduceUnlessLeft(0, safeSum))) // Success(6)
console.log(pipe(["1", "x", "3"], MArray.reduceUnlessLeft(0, safeSum))) // Failure('Invalid: x')

Signature

export declare const reduceUnlessLeft: <B, A, C>(
  b: B,
  f: (b: B, a: A, i: number) => Result.Result<B, C>
) => (self: Iterable<A>) => Result.Result<B, C>

reduceUnlessNone

Reduces self with f, returning Option.some of the final accumulator if every step succeeds, or Option.none as soon as one step returns Option.none.

  • Use when reducing with a step that may fail without context.
  • Short-circuits on the first Option.none.

Example (Reduce with possible failure)

import { Option, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const safeAdd = (acc: number, x: number) => (x >= 0 ? Option.some(acc + x) : Option.none())

console.log(pipe([1, 2, 3], MArray.reduceUnlessNone(0, safeAdd))) // Some(6)
console.log(pipe([1, -1, 3], MArray.reduceUnlessNone(0, safeAdd))) // None

Signature

export declare const reduceUnlessNone: <B, A>(
  b: B,
  f: (b: B, a: A, i: number) => Option.Option<B>
) => (self: Iterable<A>) => Option.Option<B>

unsafeGetter

Returns a function that retrieves the element of self at a given index without bounds checking.

  • Use to precompute an unchecked getter when the same array will be queried many times under a bounds invariant.
  • May return undefined (typed as A) for out-of-bounds indexes.

Example (Reusable unsafe getter)

import * as MArray from "@parischap/effect-lib/MArray"

const get = MArray.unsafeGetter([1, 2, 3])
console.log(get(1)) // 2

Signature

export declare const unsafeGetter: <A>(self: Type<A>) => MTypes.OneArgFunction<number, A>

Models

Type (interface)

Type on which this module’s functions operate.

Signature

export interface Type<out A> extends ReadonlyArray<A> {}

Predicates

hasDuplicates

Returns true if self contains at least one duplicate, comparing elements with Equal.equals.

  • Use to validate uniqueness with default equality.
  • Comparison uses Effect’s Equal.equals (structural equality for Equal-aware types, otherwise ===).

Example (Detecting duplicates)

import * as MArray from "@parischap/effect-lib/MArray"

console.log(MArray.hasDuplicates([1, 2, 2, 3])) // true
console.log(MArray.hasDuplicates([1, 2, 3])) // false

Signature

export declare const hasDuplicates: (self: Type<unknown>) => boolean

hasDuplicatesWith

Returns true if self contains at least one duplicate, comparing elements with the supplied Equivalence.

  • Use when default equality is not adequate (e.g. comparing objects by a single field).
  • Returns false for arrays with all-distinct elements.

Example (Detecting duplicates with a custom equivalence)

import { Equivalence, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const byId = Equivalence.mapInput(Equivalence.number, (o: { readonly id: number }) => o.id)
console.log(pipe([{ id: 1 }, { id: 1 }], MArray.hasDuplicatesWith(byId))) // true
console.log(pipe([{ id: 1 }, { id: 2 }], MArray.hasDuplicatesWith(byId))) // false

Signature

export declare const hasDuplicatesWith: <A>(
  isEquivalent: Equivalence.Equivalence<NoInfer<A>>
) => (self: Type<A>) => boolean

hasLength

Returns true if the length of self is exactly l.

  • Use to assert that an array has a specific number of elements.
  • Length comparison is ===.

Example (Length check)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3], MArray.hasLength(3))) // true
console.log(pipe([1, 2, 3], MArray.hasLength(2))) // false

Signature

export declare const hasLength: (l: number) => <A>(self: Type<A>) => boolean

Utility types

With (type alias)

Utility type that replaces the type of every element of an array or tuple with A.

Signature

export type With<S extends MTypes.AnyReadonlyArray, A> = { [k in keyof S]: A }

Utils

differenceSorted

Returns the elements of self not present in that. Both iterables must already be sorted according to o. Element equality is Equal.equals.

  • Use to compute a sorted set difference in a single linear pass.
  • Both inputs must be sorted; otherwise the result is undefined.

Example (Sorted difference)

import { Order, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3, 4, 5], MArray.differenceSorted(Order.number)([2, 4]))) // [1, 3, 5]

Signature

export declare const differenceSorted: <A>(o: Order.Order<A>) => (that: Iterable<A>) => (self: Iterable<A>) => Array<A>

extractFirst

Extracts the first element of self matching predicate (or refinement) and returns a pair of the extracted element (as an Option) and the remaining elements in their original order.

  • Use to find and remove the first matching element in a single pass.
  • When no element matches, returns [Option.none(), self].
  • Acts as a refinement-aware destructor: the extracted element is narrowed when a refinement is supplied.

Example (Extract first matching element)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const [match, rest] = pipe(
  [1, 3, 2, 4],
  MArray.extractFirst((n) => n > 2)
)
console.log(match) // Some(3)
console.log(rest) // [1, 2, 4]

Signature

export declare const extractFirst: {
  <A, B extends A>(
    refinement: (a: NoInfer<A>, i: number) => a is B
  ): (self: Type<A>) => MTypes.Pair<Option.Option<B>, Array<A>>
  <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Type<A>) => MTypes.Pair<Option.Option<A>, Array<A>>
}

findAll

Returns the indexes of all elements of self satisfying predicate, in ascending order.

  • Use to locate every position matching a condition.
  • Returns an empty array when no element matches.

Example (Indexes of matching elements)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"
import * as MPredicate from "@parischap/effect-lib/MPredicate"

console.log(pipe([1, 3, 2, 4], MArray.findAll(MPredicate.strictEquals(3)))) // [1]
console.log(pipe([1, 3, 2, 4, 3], MArray.findAll(MPredicate.strictEquals(3)))) // [1, 4]

Signature

export declare const findAll: <A>(predicate: Predicate.Predicate<NoInfer<A>>) => (self: Iterable<A>) => Array<number>

getFromEnd

Returns the element at position index counted from the end of self as an Option.

  • Use to access from the tail of an array.
  • index is zero-based: 0 is the last element.
  • Returns Option.none when index is out of bounds.

Example (Indexed access from the end)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3], MArray.getFromEnd(0))) // Some(3)
console.log(pipe([1, 2, 3], MArray.getFromEnd(1))) // Some(2)
console.log(pipe([1, 2, 3], MArray.getFromEnd(3))) // None

Signature

export declare const getFromEnd: (index: number) => <A>(self: Type<A>) => Option.Option<A>

groupBy

Like Array.groupBy but applies fValue to each element before collecting it into its bucket.

  • Use to group and project in a single pass.
  • Each bucket is guaranteed non-empty (typed MTypes.OverOne<B>).

Example (Group with projection)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const data = [
  { type: "a", value: 1 },
  { type: "a", value: 2 },
  { type: "b", value: 3 }
] as const

console.log(pipe(data, MArray.groupBy({ fKey: (item) => item.type, fValue: (item) => item.value })))
// { a: [1, 2], b: [3] }

Signature

export declare const groupBy: <A, B>({
  fKey,
  fValue
}: {
  readonly fKey: (a: NoInfer<A>) => string
  readonly fValue: (a: NoInfer<A>) => B
}) => (self: Iterable<A>) => Record<string, MTypes.OverOne<B>>

groupByNum

Maps the elements of self with fValue and groups the results by the numeric index returned by fKey. The output is an array of length size. Elements whose key is negative or >= size are dropped; rows for which no element maps are left as empty arrays.

  • Use to bucket elements into a fixed number of slots.
  • Together with {@link ungroup} provides a round-trip: groupByNum reverses ungroup.

Example (Bucketing by row index)

import { Tuple, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const input = [
  [0, "a"],
  [0, "b"],
  [1, "c"],
  [1, "d"]
] as ReadonlyArray<[number, string]>
console.log(pipe(input, MArray.groupByNum({ size: 2, fKey: Tuple.get(0), fValue: Tuple.get(1) })))
// [['a', 'b'], ['c', 'd']]

Signature

export declare const groupByNum: <A, B>({
  size,
  fKey,
  fValue
}: {
  readonly size: number
  readonly fKey: (a: NoInfer<A>) => number
  readonly fValue: (a: NoInfer<A>) => B
}) => (self: Type<A>) => ReadonlyArray<ReadonlyArray<B>>

longestCommonSubArray

Returns the longest common prefix of self and that, comparing elements with Equal.equals.

  • Use to find the leading elements two arrays agree on.
  • Returns an empty array when the first elements already differ.

Example (Longest common prefix)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 4], MArray.longestCommonSubArray([1, 2, 3]))) // [1, 2]
console.log(pipe([0, 1], MArray.longestCommonSubArray([1, 2]))) // []

Signature

export declare const longestCommonSubArray: <A>(that: Iterable<A>) => (self: Iterable<A>) => Array<A>

match012

Pattern-matches self by cardinality: empty, singleton, or two-or-more.

  • Use to branch type-safely on array size.
  • onSingleton receives the single element directly.
  • onOverTwo receives self typed as MTypes.ReadonlyOverTwo<A> (two-or-more).

Example (Cardinality match)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

const describe = MArray.match012({
  onEmpty: () => "empty",
  onSingleton: (x: number) => `one: ${x}`,
  onOverTwo: (xs) => `many: ${xs.length}`
})

console.log(pipe([], describe)) // 'empty'
console.log(pipe([1], describe)) // 'one: 1'
console.log(pipe([1, 2, 3], describe)) // 'many: 3'

Signature

export declare const match012: <A, B, C = B, D = B>(options: {
  readonly onEmpty: Function.LazyArg<B>
  readonly onSingleton: (self: NoInfer<A>) => C
  readonly onOverTwo: (self: MTypes.ReadonlyOverTwo<NoInfer<A>>) => D
}) => (self: Type<A>) => B | C | D

mergeSorted

Stably merges two iterables already sorted according to o.

  • Both inputs must already be sorted by o.
  • The merge is stable: equal elements from self precede equal elements from that.

Example (Merge sorted iterables)

import { Order, pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 3, 5], MArray.mergeSorted(Order.number)([2, 4, 6]))) // [1, 2, 3, 4, 5, 6]

Signature

export declare const mergeSorted: <A>(o: Order.Order<A>) => (that: Iterable<A>) => (self: Iterable<A>) => Array<A>

modifyHead

Returns a copy of self with the first element transformed by f.

  • Use to update only the leading element.
  • Returns an empty copy when self is empty.

Example (Modify first element)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(
  pipe(
    [1, 2, 3],
    MArray.modifyHead((x) => x * 2)
  )
) // [2, 2, 3]
console.log(
  pipe(
    [],
    MArray.modifyHead((x) => x * 2)
  )
) // []

Signature

export declare const modifyHead: <S extends MTypes.AnyReadonlyArray, B>(
  f: (a: Array.ReadonlyArray.Infer<S>) => B
) => (self: S) => With<S, Array.ReadonlyArray.Infer<S> | B>

modifyInit

Returns a copy of self with every element except the last transformed by f.

  • Use to apply a transformation to all elements but the trailing one.
  • Returns self unchanged when it has zero or one elements.

Example (Modify all but the last)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(
  pipe(
    [1, 2, 3, 4],
    MArray.modifyInit((x) => x * 2)
  )
) // [2, 4, 6, 4]
console.log(
  pipe(
    [5],
    MArray.modifyInit((x) => x * 2)
  )
) // [5]

Signature

export declare const modifyInit: <S extends MTypes.AnyReadonlyArray, B>(
  f: (a: Array.ReadonlyArray.Infer<S>, i: number) => B
) => (self: S) => With<S, Array.ReadonlyArray.Infer<S> | B>

modifyLast

Returns a copy of self with the last element transformed by f.

  • Use to update only the trailing element.
  • Returns an empty copy when self is empty.

Example (Modify last element)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(
  pipe(
    [1, 2, 3],
    MArray.modifyLast((x) => x * 2)
  )
) // [1, 2, 6]
console.log(
  pipe(
    [],
    MArray.modifyLast((x) => x * 2)
  )
) // []

Signature

export declare const modifyLast: <S extends MTypes.AnyReadonlyArray, B>(
  f: (a: Array.ReadonlyArray.Infer<S>) => B
) => (self: S) => With<S, Array.ReadonlyArray.Infer<S> | B>

modifyTail

Returns a copy of self with every element except the first transformed by f.

  • Use to apply a transformation to all elements but the leading one.
  • Returns self unchanged when it has zero or one elements.

Example (Modify all but the first)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(
  pipe(
    [1, 2, 3, 4],
    MArray.modifyTail((x) => x * 2)
  )
) // [1, 4, 6, 8]
console.log(
  pipe(
    [5],
    MArray.modifyTail((x) => x * 2)
  )
) // [5]

Signature

export declare const modifyTail: <S extends MTypes.AnyReadonlyArray, B>(
  f: (a: Array.ReadonlyArray.Infer<S>, i: number) => B
) => (self: S) => With<S, Array.ReadonlyArray.Infer<S> | B>

pad

Same as Array.pad but the result is typed as a fixed-size Tuple of length N instead of a plain array.

  • Use when the resulting length is part of the type and downstream code relies on it.
  • Pads with fill when shorter than n; truncates when longer.

Example (Padding to a fixed length)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3], MArray.pad(5, 0))) // [1, 2, 3, 0, 0]

Signature

export declare const pad: <A, T, N extends number>(
  n: N,
  fill: T
) => MTypes.OneArgFunction<Type<A>, MTypes.Tuple<A | T, N>>

removeEmptyAndJoin

Joins the strings of self with sep, ignoring empty strings so they do not introduce extra separators.

  • Use when assembling fragments coming from heterogeneous sources where some may be empty.
  • The output never contains two consecutive sep’s nor a leading/trailing sep.

Example (Joining without empty fragments)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe(["a", "", "b", "", "c"], MArray.removeEmptyAndJoin(", "))) // 'a, b, c'

Signature

export declare const removeEmptyAndJoin: (sep: string) => MTypes.OneArgFunction<Iterable<string>, string>

splitAtFromRight

Splits self into two segments, the second containing at most the last n elements.

  • Use to take a fixed-size suffix while keeping the rest.
  • When n >= self.length, the first segment is empty.
  • n must be a non-negative integer; 0 puts everything in the first segment.

Example (Split from the right)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3, 4, 5], MArray.splitAtFromRight(2))) // [[1, 2, 3], [4, 5]]
console.log(pipe([1, 2, 3], MArray.splitAtFromRight(0))) // [[1, 2, 3], []]

Signature

export declare const splitAtFromRight: (n: number) => <A>(self: Type<A>) => [beforeIndex: Array<A>, fromIndex: Array<A>]

splitNonEmptyAtFromRight

Variant of {@link splitAtFromRight} for non-empty arrays where the second segment is guaranteed non-empty.

  • n must be >= 1.
  • Returns the second segment typed as MTypes.OverOne<A>.

Example (Non-empty split from the right)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3, 4] as const, MArray.splitNonEmptyAtFromRight(2))) // [[1, 2], [3, 4]]

Signature

export declare const splitNonEmptyAtFromRight: (
  n: number
) => <A>(self: MTypes.ReadonlyOverOne<A>) => [beforeIndex: Array<A>, fromIndex: MTypes.OverOne<A>]

takeBut

Returns all elements of self except the last n.

  • Use to drop a suffix of fixed size.
  • When n >= self.length, returns an empty array.
  • n should be a non-negative integer.

Example (Drop trailing elements)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3, 4], MArray.takeBut(2))) // [1, 2]
console.log(pipe([1, 2, 3], MArray.takeBut(5))) // []

Signature

export declare const takeBut: (n: number) => <A>(self: Type<A>) => Array<A>

takeRightBut

Returns all elements of self except the first n.

  • Use to drop a prefix of fixed size.
  • When n >= self.length, returns an empty array.
  • n should be a non-negative integer.

Example (Drop leading elements)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3, 4], MArray.takeRightBut(2))) // [3, 4]
console.log(pipe([1, 2, 3], MArray.takeRightBut(5))) // []

Signature

export declare const takeRightBut: (n: number) => <A>(self: Type<A>) => Array<A>

ungroup

Flattens a two-dimensional array, tagging each element with the index of its source row.

  • Use as the inverse companion to {@link groupByNum}: groupByNum undoes ungroup when fKey/fValue extract the row index and the original element respectively.
  • Order is preserved: rows are visited in order, and each row is flattened left to right.

Example (Tagged flatten)

import * as MArray from "@parischap/effect-lib/MArray"

console.log(
  MArray.ungroup([
    [1, 2, 3],
    [4, 5]
  ])
)
// [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5]]

Signature

export declare const ungroup: <A>(as: Type<Type<A>>) => Array<[number, A]>

unsafeGet

Returns the element of self at index without bounds checking.

  • Use only when bounds are guaranteed by construction; otherwise prefer Array.get.
  • Returns undefined (typed as A) for out-of-bounds indexes.

Example (Unchecked access)

import { pipe } from "effect"
import * as MArray from "@parischap/effect-lib/MArray"

console.log(pipe([1, 2, 3], MArray.unsafeGet(0))) // 1
console.log(pipe([1, 2, 3], MArray.unsafeGet(10))) // undefined

Signature

export declare const unsafeGet: (index: number) => <A>(self: Type<A>) => A