Search results
compose2Flipped :: forall a b x y. (x -> y -> a) -> (a -> b) -> x -> y -> b
composeSecond :: forall a b x y. (x -> b -> a) -> (y -> b) -> x -> y -> a
\f g x y -> f x (g y)
goldfinch :: forall d c b a. (b -> c -> d) -> (a -> c) -> a -> b -> d
G combinator - goldfinch
BBC
Λ a b c d . (b → c → d) → (a → c) → a → b → d
λ f g x y . f y (g x)
on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c
The on function is used to change the domain of a binary operator.
For example, we can create a function which compares two records based on the values of their x properties:
compareX :: forall r. { x :: Number | r } -> { x :: Number | r } -> Ordering
compareX = compare `on` _.x
on :: forall c b a. (b -> b -> c) -> (a -> b) -> a -> a -> c
Psi combinator - psi bird - on
Λ a b . (b → b → c) → (a → b) → a → a → c
λ f g . λ x y . f (g x) (g y)
on :: forall c b a. (a -> a -> b) -> (c -> a) -> c -> c -> b
psi :: forall c b a. (a -> a -> b) -> (c -> a) -> (c -> c -> b)
verifyScannable :: forall b a f. Eq (f b) => Functor f => Foldable f => Scannable f => (b -> a -> b) -> (a -> b) -> b -> f a -> Boolean
absorbtion :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> Boolean
absorbtion :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> Boolean
onemore :: forall t24 t25 t27 t28. (t25 -> t27 -> t28) -> (t24 -> t25) -> (t24 -> t27) -> t24 -> t28
antitransitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
intransitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
transitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
antitransitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
intransitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
transitive :: forall b a. HeytingAlgebra b => (a -> a -> b) -> a -> a -> a -> b
associative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
cancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
leftCancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
leftUnar :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
rightCancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
rightUnar :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
associative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
cancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
leftCancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
leftUnar :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
rightCancellative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
rightUnar :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
verifySemilattice :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
associative :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
f (f x y) z == f x (f y z)?
splay1 :: forall a b c. (a -> b -> c) -> (a -> b) -> a -> c
verifySemilattice :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Boolean
s :: forall c b a. (a -> b -> c) -> (a -> b) -> (a -> c)
monotonic :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a -> a
monotonic :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a -> a
everything :: forall a r. Data a => (r -> r -> r) -> (forall b. Data b => b -> r) -> a -> r
Summarise all nodes in top-down, left-to-right
compose3Flipped :: forall a b x y z. (x -> y -> z -> a) -> (a -> b) -> x -> y -> z -> b
composeThird :: forall a b x y z. (x -> y -> b -> a) -> (z -> b) -> x -> y -> z -> a
\f g x y z -> f x y (g z)
jay :: forall b a. (a -> b -> b) -> a -> b -> a -> b
J combinator - Jay
B(BC)(W(BC(B(BBB))))
Λ a b c d . (a → b → b) → a → b → a → b
λ f x y z . f x (f z y)
splay2 :: forall a b c d. (a -> b -> c -> d) -> (a -> b -> c) -> a -> b -> d
compose2Second :: forall a b x y z. (x -> b -> a) -> (y -> z -> b) -> x -> y -> z -> a
\f g x y z -> f x (g y z)
distributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
leftDistributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
rightDistributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
distributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
leftDistributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
rightDistributive :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Boolean
bifoldl :: forall p a b c. Bifoldable p => (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
bifoldlDefault :: forall p a b c. Bifoldable p => (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> c
A default implementation of bifoldl using bifoldMap.
Note: when defining a Bifoldable instance, this function is unsafe to
use in combination with bifoldMapDefaultL.
applyThird :: forall x y z a. (y -> z -> x -> a) -> x -> y -> z -> a
\f x y z -> f y z x
robinstar :: forall d c b a. (b -> c -> a -> d) -> a -> b -> c -> d
R* combinator - robin once removed
CC
Λ a b c d . (b → c → a → d) → a → b → c → d
λ f x y z . f y z x
unsafeOptField_helper :: forall r val obj. r -> (val -> r) -> String -> obj -> r
composeKleisli :: forall a b c m. Bind m => (a -> m b) -> (b -> m c) -> a -> m c
Forwards Kleisli composition.
For example:
import Data.Array (head, tail)
third = tail >=> tail >=> head
compose2SecondFlipped :: forall a b x y z. (y -> z -> b) -> (x -> b -> a) -> x -> y -> z -> a
fold :: forall event b a. IsEvent event => (a -> b -> b) -> event a -> b -> event b
under2 :: forall t a s b. Newtype t a => Newtype s b => (a -> t) -> (t -> t -> s) -> a -> a -> b
The opposite of over2: lowers a binary function that operates on Newtyped
values to operate on the wrapped value instead.
bifoldr :: forall p a b c. Bifoldable p => (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c
bifoldrDefault :: forall p a b c. Bifoldable p => (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> c
A default implementation of bifoldr using bifoldMap.
Note: when defining a Bifoldable instance, this function is unsafe to
use in combination with bifoldMapDefaultR.
memoize3 :: forall a b c d. Tabulate a => Tabulate b => Tabulate c => (a -> b -> c -> d) -> a -> b -> c -> d
Memoize a function of three arguments
compose2 :: forall a b x y. (a -> b) -> (x -> y -> a) -> x -> y -> b
\f g x y -> f (g x y)
memoize3 :: forall d c b a. Tabulate a => Tabulate b => Tabulate c => (a -> b -> c -> d) -> a -> b -> c -> d
Memoize a function of three arguments
becard :: forall d c b a. (c -> d) -> (b -> c) -> (a -> b) -> a -> d
B3 combinator - becard
B(BB)B
Λ a b c d . (c → d) → (b → c) → (a → b) → a → d
λ f g h x . f (g (h x))
leftSemimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
medial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
rightSemimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
semimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
leftSemimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
medial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
rightSemimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
semimedial :: forall a. Eq a => (a -> a -> a) -> a -> a -> a -> a -> Boolean
foldTree :: forall x b a. (a -> x -> b) -> (List b -> x) -> Tree a -> b
Fold over a 'Tree'.
lift2 :: forall a b c f. Apply f => (a -> b -> c) -> f a -> f b -> f c
Lift a function of two arguments to a function which accepts and returns
values wrapped with the type constructor f.
lift2 add (Just 1) (Just 2) == Just 3
lift2 add Nothing (Just 2) == Nothing
over2 :: forall t a s b. Newtype t a => Newtype s b => (a -> t) -> (a -> a -> b) -> t -> t -> s
Lifts a binary function to operate over newtypes.
newtype Meter = Meter Int
derive newtype instance newtypeMeter :: Newtype Meter _
newtype SquareMeter = SquareMeter Int
derive newtype instance newtypeSquareMeter :: Newtype SquareMeter _
area :: Meter -> Meter -> SquareMeter
area = over2 Meter (*)
The above example also demonstrates that the return type is polymorphic here too.
composeSecondFlipped :: forall a b x y. (y -> b) -> (x -> b -> a) -> x -> y -> a
parLift2 :: forall a b c g m. Parallel g m => (a -> b -> c) -> m a -> m b -> m c
distributive :: forall a. Eq a => (a -> a) -> (a -> a -> a) -> a -> a -> Boolean
f (g x y) == g (f x) (f y)?
liftI2 :: forall f a b c. Additive f => (a -> b -> c) -> f a -> f b -> f c
Apply a function component-wise (intersection semantics)
phoenix :: forall f c b a. Apply f => (a -> b -> c) -> f a -> f b -> f c
Φ combinator - phoenix
Λ a b c d . (b → c → d) → (a → b) → (a → c) → a → d
λ f g h x . f (g x) (h x)
starling' :: forall f c b a. Apply f => (a -> b -> c) -> f a -> f b -> f c
S' combinator - starling prime
Λ a b c d . (b → c → d) → (a → b) → (a → c) → a → d
λ f g h x . f (g x) (h x)
zipWith :: forall f c b a. Container f => (a -> b -> c) -> f a -> f b -> f c
composeKleisliFlipped :: forall a b c m. Bind m => (b -> m c) -> (a -> m b) -> a -> m c
Backwards Kleisli composition.
flip :: forall a b c. (a -> b -> c) -> b -> a -> c
Given a function that takes two arguments, applies the arguments to the function in a swapped order.
flip append "1" "2" == append "2" "1" == "21"
const 1 "two" == 1
flip const 1 "two" == const "two" 1 == "two"
under :: forall t a s b. Newtype t a => Newtype s b => (a -> t) -> (t -> s) -> a -> b
The opposite of over: lowers a function that operates on Newtyped
values to operate on the wrapped value instead.
newtype Degrees = Degrees Number
derive instance newtypeDegrees :: Newtype Degrees _
newtype NormalDegrees = NormalDegrees Number
derive instance newtypeNormalDegrees :: Newtype NormalDegrees _
normaliseDegrees :: Degrees -> NormalDegrees
normaliseDegrees (Degrees deg) = NormalDegrees (deg % 360.0)
asNormalDegrees :: Number -> Number
asNormalDegrees = under Degrees normaliseDegrees
As with over the Newtype is polymorphic, as illustrated in the example
above - both Degrees and NormalDegrees are instances of Newtype,
so even though normaliseDegrees changes the result type we can still put
a Number in and get a Number out via under.
applySecond :: forall x y a. (y -> x -> a) -> x -> y -> a
\f x y -> f y x
(flip)
cardinal :: forall c b a. (a -> b -> c) -> b -> a -> c
C combinator - cardinal
S(BBS)(KK)
Λ a b c . (a → b → c) → b → a → c
λ f x y . f y x
flip :: forall c b a. (a -> b -> c) -> (b -> a -> c)
Flips the first two arguments of a function.
"a" :add "b" -- "ab"
"a" :flip add "b" -- "ba"
memoCompose :: forall a b c. (a -> b) -> (b -> c) -> a -> c
Memoize the composition of two functions
vireostar :: forall c b a. (a -> b -> c) -> b -> a -> c
V* combinator - vireo once removed
CF
Λ a b c d . (b → a → b → d) → a → b → b → d
λ f x y z . f y x z
forkActionState :: forall m s. Plus m => MonadAff m => m (s -> s) -> (s -> m s) -> (s -> m s)
Another common variant on the forkAction pattern.
The action m (s->s) may take a while (should not be restarted) and returns a state modification function
The gui s -> m s takes in the current state, and modifies it on events
Note that forkActionState axn has the shape (s -> m s) -> (s -> m s). So it can be "stacked" to fork multiple actions.
e.g. forkActionState axn1 $ forkActionState axn2 $ forkActionState axn3 $ render initialState.
liftU2 :: forall f a. Additive f => (a -> a -> a) -> f a -> f a -> f a
Apply a function to non-zero values (union semantics)
on :: forall @sym f1 f2 a b r1 r2. Newtype f2 (Variant r2) => Newtype f1 (Variant r1) => Cons sym a r1 r2 => IsSymbol sym => (a -> b) -> (f1 -> b) -> f2 -> b
caseDeposit :: forall a d. Deposit d => (Source -> a) -> (Mineral -> a) -> d -> a
over :: forall t a s b. Newtype t a => Newtype s b => (a -> t) -> (a -> b) -> t -> s
Lifts a function operate over newtypes. This can be used to lift a
function to manipulate the contents of a single newtype, somewhat like
map does for a Functor:
newtype Label = Label String
derive instance newtypeLabel :: Newtype Label _
toUpperLabel :: Label -> Label
toUpperLabel = over Label String.toUpper
But the result newtype is polymorphic, meaning the result can be returned as an alternative newtype:
newtype UppercaseLabel = UppercaseLabel String
derive instance newtypeUppercaseLabel :: Newtype UppercaseLabel _
toUpperLabel' :: Label -> UppercaseLabel
toUpperLabel' = over Label String.toUpper
fromKillSignal' :: forall r. (Int -> r) -> (String -> r) -> KillSignal -> r
memoize2 :: forall a b c. Tabulate a => Tabulate b => (a -> b -> c) -> a -> b -> c
Memoize a function of two arguments
memoize2 :: forall c b a. Tabulate a => Tabulate b => (a -> b -> c) -> a -> b -> c
Memoize a function of two arguments
idstarstar :: forall c b a. (a -> b -> c) -> a -> b -> c
I** combinator - id bird twice removed
Λ a b c . (a → b → c) → a → b → c
λ f x y . f x y
moldl :: forall t e m. Moldable t e => (m -> e -> m) -> m -> t -> m
moldlDefault :: forall m e t. Moldable t e => (m -> e -> m) -> m -> t -> m
A default implementation of moldl based on moldMap
moldr :: forall t e m. Moldable t e => (e -> m -> m) -> m -> t -> m
moldrDefault :: forall m e t. Moldable t e => (e -> m -> m) -> m -> t -> m
A default implementation of moldr based on moldMap
down :: forall f a c d. Functor f => Semiring a => (a -> c -> d) -> a -> f c -> f d
foldlMultiVal :: forall xs acc. MultiVal xs => (acc -> Val -> acc) -> acc -> xs -> acc
foldl :: forall a. (a -> Byte -> a) -> a -> ByteString -> a
Fold over the bytes left-to-right (first byte first).
foldr :: forall a. (Byte -> a -> a) -> a -> ByteString -> a
Fold over the bytes right-to-left (last byte first).
falsehoodPreserving :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a
truthPreserving :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a
falsehoodPreserving :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a
truthPreserving :: forall a. HeytingAlgebra a => Eq a => (a -> a -> a) -> a -> a -> a
foldl :: forall a. (a -> DataBuff -> a) -> a -> Builder -> a
Stack-safe foldl over a Builder. O(n)
reifyEq :: forall r a. (a -> a -> Boolean) -> (forall s. Reifies s (ReifiedEq a) => Proxy s -> r) -> r
reifyOrd :: forall r a. (a -> a -> Ordering) -> (forall s. Reifies s (ReifiedOrd a) => Proxy s -> r) -> r
foldM :: forall m a. MonadRec m => (a -> DataBuff -> m a) -> a -> Builder -> m a
Stack-safe foldM over a Builder. O(n).
compose :: forall c b a. (b -> c) -> (a -> b) -> (a -> c)
Returns a new function that calls the first function with the result of calling the second.
let addTwo x = x + 2
let double x = x * 2
let addTwoThenDouble x = addTwo :compose double
addTwoThenDouble 3 -- 10
This is function composition.
foldForest :: forall x b a. (a -> x -> b) -> (List b -> x) -> List (Tree a) -> x
Fold over a list of trees.
scanl :: forall a b f. Traversable f => (b -> a -> b) -> b -> f a -> f b
Fold a data structure from the left, keeping all intermediate results
instead of only the final result. Note that the initial value does not
appear in the result (unlike Haskell's Prelude.scanl).
scanl (+) 0 [1,2,3] = [1,3,6]
scanl (-) 10 [1,2,3] = [9,7,4]
scanr :: forall a b f. Traversable f => (a -> b -> b) -> b -> f a -> f b
Fold a data structure from the right, keeping all intermediate results
instead of only the final result. Note that the initial value does not
appear in the result (unlike Haskell's Prelude.scanr).
scanr (+) 0 [1,2,3] = [6,5,3]
scanr (flip (-)) 10 [1,2,3] = [4,5,7]
fold :: forall event a b. IsEvent event => (b -> a -> b) -> b -> event a -> event b
Fold over values received from some Event, creating a new Event.
gateBy :: forall a b event. IsEvent event => (Maybe a -> b -> Boolean) -> event a -> event b -> event b
Generalised form of gateBy, allowing for any predicate between the two
events. The predicate will not be evaluated until a value from the first event is received.
gateBy :: forall event b a. IsEvent event => (Maybe a -> b -> Boolean) -> event a -> event b -> event b
Generalised form of gateBy, allowing for any predicate between the two
events. Until a value from the first event is received, Nothing will be
passed to the predicate.
reifySemigroup :: forall r a. (a -> a -> a) -> (forall s. Reifies s (ReifiedSemigroup a) => Proxy s -> r) -> r
scanl :: forall f b a. Scannable f => (b -> a -> b) -> b -> f a -> f b
scanr :: forall f b a. Scannable f => (a -> b -> b) -> b -> f a -> f b
traverse :: forall f t a. Coercible (f a) (f t) => Newtype t a => (a -> t) -> (a -> f a) -> t -> f t
Similar to the function from the Traversable class, but operating within
a newtype instead.
imap :: forall f a b. Invariant f => (a -> b) -> (b -> a) -> f a -> f b
imapF :: forall f a b. Functor f => (a -> b) -> (b -> a) -> f a -> f b
As all Functors are also trivially Invariant, this function can be
used as the imap implementation for any types that has an existing
Functor instance.
imapC :: forall f a b. Contravariant f => (a -> b) -> (b -> a) -> f a -> f b
As all Contravariant functors are also trivially Invariant, this function can be used as the imap implementation for any types that have an existing Contravariant instance.
jacobiIdentity :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> a -> Boolean
mapAccum :: forall c b a event. IsEvent event => (a -> b -> Tuple b c) -> event a -> b -> event c
Map over an event with an accumulator.
For example, to keep the index of the current event:
mapAccum (\x i -> Tuple (i + 1) (Tuple x i)) 0`.
jacobiIdentity :: forall a. Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> a -> Boolean
insertBy :: forall f a. Container f => (a -> a -> Ordering) -> a -> f a -> f a
maybe' :: forall a b. (Unit -> b) -> (a -> b) -> Maybe a -> b
Similar to maybe but for use in cases where the default value may be
expensive to compute. As PureScript is not lazy, the standard maybe has
to evaluate the default value before returning the result, whereas here
the value is only computed when the Maybe is known to be Nothing.
maybe' (\_ -> x) f Nothing == x
maybe' (\_ -> x) f (Just y) == f y
allWithIndex :: forall i a b f. FoldableWithIndex i f => HeytingAlgebra b => (i -> a -> b) -> f a -> b
allWithIndex f is the same as and <<< mapWithIndex f; map a function over the
structure, and then get the conjunction of the results.
anyWithIndex :: forall i a b f. FoldableWithIndex i f => HeytingAlgebra b => (i -> a -> b) -> f a -> b
anyWithIndex f is the same as or <<< mapWithIndex f; map a function over the
structure, and then get the disjunction of the results.
foldMapWithIndex :: forall i f a m. FoldableWithIndex i f => Monoid m => (i -> a -> m) -> f a -> m
foldMapWithIndexDefaultL :: forall i f a m. FoldableWithIndex i f => Monoid m => (i -> a -> m) -> f a -> m
A default implementation of foldMapWithIndex using foldlWithIndex.
Note: when defining a FoldableWithIndex instance, this function is
unsafe to use in combination with foldlWithIndexDefault.
foldMapWithIndexDefaultR :: forall i f a m. FoldableWithIndex i f => Monoid m => (i -> a -> m) -> f a -> m
A default implementation of foldMapWithIndex using foldrWithIndex.
Note: when defining a FoldableWithIndex instance, this function is
unsafe to use in combination with foldrWithIndexDefault.
mapWithIndex :: forall i f a b. FunctorWithIndex i f => (i -> a -> b) -> f a -> f b
onTextChange :: forall m. MonadEffect m => (Ops -> Ops -> Source -> Effect Unit) -> (MultipleErrors -> Effect Unit) -> Editor -> m Unit
https://quilljs.com/docs/api/#text-change
expectSatisfy :: forall m a. MonadThrow Error m => Show a => a -> (a -> Boolean) -> String -> m Unit
discard :: forall m a b c. Bind m => (a -> m b) -> (Unit -> (b -> m c)) -> (a -> m c)
subscriptionEventOpts :: forall opts c. SubscriptionClient c opts => (opts -> opts) -> c -> String -> Json -> Emitter Json
watchQueryEventOpts :: forall opts c. WatchQueryClient c opts => (opts -> opts) -> c -> String -> Json -> Emitter Json
foldl :: forall f a b. Foldable f => (b -> a -> b) -> b -> f a -> b
foldlDefault :: forall f a b. Foldable f => (b -> a -> b) -> b -> f a -> b
A default implementation of foldl using foldMap.
Note: when defining a Foldable instance, this function is unsafe to use
in combination with foldMapDefaultL.
foldlDefault :: forall i f a b. FoldableWithIndex i f => (b -> a -> b) -> b -> f a -> b
A default implementation of foldl using foldlWithIndex
foldr :: forall f a b. Foldable f => (a -> b -> b) -> b -> f a -> b
foldrDefault :: forall f a b. Foldable f => (a -> b -> b) -> b -> f a -> b
A default implementation of foldr using foldMap.
Note: when defining a Foldable instance, this function is unsafe to use
in combination with foldMapDefaultR.
foldrDefault :: forall i f a b. FoldableWithIndex i f => (a -> b -> b) -> b -> f a -> b
A default implementation of foldr using foldrWithIndex