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 justReadonlyArray<A>; functions never mutate the input.- All functions are curried, data-last — call as
MArray.fn(arg)(self)orpipe(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*Withvariants take an explicitEquivalence.
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 curriedArray.unfold: keep generating untilfreturnsOption.none. - With
seedEquivalence, every seed is recorded; if the same seed reappears,cycleSourceis asomeof theAproduced 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.nonefor 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.nonereturned byf.
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 asA) 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 forEqual-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
falsefor 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.
indexis zero-based:0is the last element.- Returns
Option.nonewhenindexis 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:
groupByNumreversesungroup.
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.
onSingletonreceives the single element directly.onOverTworeceivesselftyped asMTypes.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
selfprecede equal elements fromthat.
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
selfis 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
selfunchanged 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
selfis 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
selfunchanged 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
fillwhen shorter thann; 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/trailingsep.
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. nmust be a non-negative integer;0puts 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.
nmust 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. nshould 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. nshould 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}:
groupByNumundoesungroupwhenfKey/fValueextract 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 asA) 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