/* * Copyright 2025 Ry Wiese * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */////// Trait for types that support iterating over their elements with `forEach`, and its functions.///pubmod ForEach {////// Trait for types that support iterating over their elements with `forEach`.///pubtraitForEach[t] {////// The type of elements in the data structure.///typeElm: Type////// The effect of `forEach`.///typeAef: Eff = {}////// Applies `f` to each element in the data structure.///pubdefforEach(f: ForEach.Elm[t] -> Unit \ ef, t: t): Unit \ (ef + ForEach.Aef[t]) }////// Type of `ForEach` views that pair each element with its index.///pubenumWithIndex[t](t)instanceForEach[WithIndex[t]] withForEach[t] {typeElm = (Int32, ForEach.Elm[t])typeAef = ForEach.Aef[t]pubdefforEach(f: ((Int32, ForEach.Elm[t])) -> Unit \ ef, t: WithIndex[t]): Unit \ ef + ForEach.Aef[t] = regionrc {let WithIndex.WithIndex(base) = t;letindexRef = Ref.fresh(rc, 0);base |> ForEach.forEach(elm -> {letindex = indexRef |> Ref.get;f((index, elm));indexRef |> Ref.put(index+1) } ) } }////// Returns a view for `m` that wraps each element with its index.///pubdefwithIndex(m: t): WithIndex[t] withForEach[t] = WithIndex.WithIndex(m)////// Type of `ForEach` views that filter out elements that do not match a predicate.///pubenumWithFilter[t, a](a -> Bool, t)instanceForEach[WithFilter[t, a]] withForEach[t] whereForEach.Elm[t] ~ a {typeElm = atypeAef = ForEach.Aef[t]pubdefforEach(f: a -> Unit \ ef, t: WithFilter[t, a]): Unit \ ef + ForEach.Aef[t] =let WithFilter.WithFilter(p, base) = t;base |> ForEach.forEach(elm -> if (p(elm)) { f(elm) }) }////// Returns a view for `m` that filters out elements that don't match `p`.///pubdefwithFilter(p: a -> Bool, m: t): WithFilter[t, a] withForEach[t] whereForEach.Elm[t] ~ a = WithFilter.WithFilter(p, m)////// Type of `ForEach` views that apply a mapping function to each element.///pubenumWithMap[t, a, b](a -> b, t)instanceForEach[WithMap[t, a, b]] withForEach[t] whereForEach.Elm[t] ~ a {typeElm = btypeAef = ForEach.Aef[t]pubdefforEach(f: b -> Unit \ ef, t: WithMap[t, a, b]): Unit \ ef + ForEach.Aef[t] =let WithMap.WithMap(mapper, base) = t;base |> ForEach.forEach(elm -> f(mapper(elm))) }////// Returns a view for `m` that applies `f` to each element.///pubdefwithMap(f: a -> b, m: t): WithMap[t, a, b] withForEach[t] = WithMap.WithMap(f, m)////// Type of views that zip two `Iterable` instances together.///pubenumWithZip[s, t](s, t)instanceForEach[WithZip[s, t]] withIterable[s], Iterable[t] {typeElm = (Iterable.Elm[s], Iterable.Elm[t])typeAef = Iterable.Aef[s] + Iterable.Aef[t]pubdefforEach(f: ((Iterable.Elm[s], Iterable.Elm[t])) -> Unit \ ef, t: WithZip[s, t]): Unit \ ef + Iterable.Aef[s] + Iterable.Aef[t] =let WithZip.WithZip(xs, ys) = t;regionrc { (Iterable.iterator(rc, xs) `Iterator.zip`Iterable.iterator(rc, ys)) |> Iterator.forEach(f) } }////// Returns a view that zips `left` and `right` together.///pubdefwithZip(left: s, right: t): WithZip[s, t] withIterable[s], Iterable[t] = WithZip.WithZip(left, right)}