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

Array.ts 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 pipe(self, MArray.fn(arg)).
  • Equality-based functions (e.g. hasDuplicates, longestCommonSubArray, differenceSorted) compare with Equal.equals. The *With variants take an explicit Equivalence.

Common tasks

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

Exports Grouped by Category


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]

See

  • MIterable.unfold — lazy counterpart

Signature

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>
}

Source

unfoldNonEmpty

Variant of 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 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]

See

  • unfold — variant returning a possibly empty array

Signature

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>
}

Source

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

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

Source

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')

See

  • mapUnlessNone — variant using Option

Signature

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>

Source

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

See

  • mapUnlessLeft — variant carrying an explicit error

Signature

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>>

Source

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')

See

  • reduceUnlessNone — variant using Option

Signature

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>

Source

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

See

  • reduceUnlessLeft — variant carrying an explicit error

Signature

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

Source

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

See

  • getter — safe alternative returning Option

Signature

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

Source

Models

Type (interface)

Type on which this module’s functions operate.

Signature

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

Source

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/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

See

  • hasDuplicatesWith — variant taking a custom Equivalence

Signature

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

Source

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

See

  • hasDuplicates — variant using Equal.equals

Signature

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

Source

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

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

Source

Utility types

With (type alias)

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

Signature

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

Source

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]

See

  • MIterable.differenceSorted — lazy counterpart

Signature

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

Source

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

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>>
}

Source

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]

See

  • MIterable.findAll — lazy counterpart

Signature

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

Source

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

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

Source

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

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>>

Source

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 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']]

See

  • ungroup — companion that produces [index, value] pairs

Signature

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>>

Source

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]))) // []

See

  • MIterable.longestCommonSubArray — lazy counterpart

Signature

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

Source

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<number, string, string, string>({
  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

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

Source

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]

See

  • MIterable.mergeSorted — lazy counterpart

Signature

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

Source

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)
  )
) // []

See

  • modifyLast — symmetric variant updating the last element
  • MIterable.modifyHead — lazy counterpart

Signature

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

Source

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]

See

  • modifyTail — symmetric variant keeping the head fixed

Signature

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>

Source

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)
  )
) // []

See

  • modifyHead — symmetric variant updating the first element

Signature

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

Source

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]

See

  • modifyInit — symmetric variant keeping the last element fixed
  • MIterable.modifyTail — lazy counterpart

Signature

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>

Source

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

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

Source

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

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

Source

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

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

Source

splitNonEmptyAtFromRight

Variant of 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

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

Source

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))) // []

See

  • takeRightBut — symmetric variant dropping the leading elements

Signature

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

Source

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))) // []

See

  • takeBut — symmetric variant dropping the trailing elements
  • MIterable.takeRightBut — lazy counterpart

Signature

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

Source

ungroup

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

  • Use as the inverse companion to 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]]

See

  • groupByNum — reverses ungroup
  • MIterable.ungroup — lazy counterpart

Signature

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

Source

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

See

  • getter — safe alternative returning Option

Signature

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

Source