2023-07-24 16:43:07 +02:00
|
|
|
// Copyright (c) 2023 IBM Corp.
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package generic
|
|
|
|
|
|
|
|
import (
|
|
|
|
A "github.com/IBM/fp-go/array/generic"
|
|
|
|
F "github.com/IBM/fp-go/function"
|
2024-02-06 21:35:33 +01:00
|
|
|
C "github.com/IBM/fp-go/internal/chain"
|
2023-07-24 16:43:07 +02:00
|
|
|
"github.com/IBM/fp-go/internal/utils"
|
|
|
|
IO "github.com/IBM/fp-go/iooption/generic"
|
2023-08-10 18:08:11 +02:00
|
|
|
M "github.com/IBM/fp-go/monoid"
|
2023-08-04 17:12:24 +02:00
|
|
|
N "github.com/IBM/fp-go/number"
|
2023-07-24 16:43:07 +02:00
|
|
|
O "github.com/IBM/fp-go/option"
|
2024-02-12 10:33:42 +01:00
|
|
|
P "github.com/IBM/fp-go/pair"
|
2023-07-24 16:43:07 +02:00
|
|
|
)
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
// Next returns the iterator for the next element in an iterator `P.Pair`
|
|
|
|
func Next[GU ~func() O.Option[P.Pair[GU, U]], U any](m P.Pair[GU, U]) GU {
|
|
|
|
return P.Head(m)
|
2023-11-10 13:46:10 +01:00
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
// Current returns the current element in an iterator `P.Pair`
|
|
|
|
func Current[GU ~func() O.Option[P.Pair[GU, U]], U any](m P.Pair[GU, U]) U {
|
|
|
|
return P.Tail(m)
|
2023-11-10 13:46:10 +01:00
|
|
|
}
|
|
|
|
|
2023-07-24 16:43:07 +02:00
|
|
|
// From constructs an array from a set of variadic arguments
|
2024-02-12 10:33:42 +01:00
|
|
|
func From[GU ~func() O.Option[P.Pair[GU, U]], U any](data ...U) GU {
|
2023-07-24 16:43:07 +02:00
|
|
|
return FromArray[GU](data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Empty returns the empty iterator
|
2024-02-12 10:33:42 +01:00
|
|
|
func Empty[GU ~func() O.Option[P.Pair[GU, U]], U any]() GU {
|
2023-07-24 16:43:07 +02:00
|
|
|
return IO.None[GU]()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Of returns an iterator with one single element
|
2024-02-12 10:33:42 +01:00
|
|
|
func Of[GU ~func() O.Option[P.Pair[GU, U]], U any](a U) GU {
|
|
|
|
return IO.Of[GU](P.MakePair(Empty[GU](), a))
|
2023-07-24 16:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// FromArray returns an iterator from multiple elements
|
2024-02-12 10:33:42 +01:00
|
|
|
func FromArray[GU ~func() O.Option[P.Pair[GU, U]], US ~[]U, U any](as US) GU {
|
2023-07-24 16:43:07 +02:00
|
|
|
return A.MatchLeft(Empty[GU], func(head U, tail US) GU {
|
2024-02-12 10:33:42 +01:00
|
|
|
return func() O.Option[P.Pair[GU, U]] {
|
|
|
|
return O.Of(P.MakePair(FromArray[GU](tail), head))
|
2023-07-24 16:43:07 +02:00
|
|
|
}
|
|
|
|
})(as)
|
|
|
|
}
|
|
|
|
|
2023-08-07 22:35:06 +02:00
|
|
|
// reduce applies a function for each value of the iterator with a floating result
|
2024-02-12 10:33:42 +01:00
|
|
|
func reduce[GU ~func() O.Option[P.Pair[GU, U]], U, V any](as GU, f func(V, U) V, initial V) V {
|
2023-08-07 22:35:06 +02:00
|
|
|
next, ok := O.Unwrap(as())
|
|
|
|
current := initial
|
|
|
|
for ok {
|
|
|
|
// next (with bad side effect)
|
2023-11-10 13:46:10 +01:00
|
|
|
current = f(current, Current(next))
|
|
|
|
next, ok = O.Unwrap(Next(next)())
|
2023-08-07 22:35:06 +02:00
|
|
|
}
|
|
|
|
return current
|
|
|
|
}
|
|
|
|
|
2023-07-24 16:43:07 +02:00
|
|
|
// Reduce applies a function for each value of the iterator with a floating result
|
2024-02-12 10:33:42 +01:00
|
|
|
func Reduce[GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(V, U) V, initial V) func(GU) V {
|
2023-08-07 22:35:06 +02:00
|
|
|
return F.Bind23of3(reduce[GU, U, V])(f, initial)
|
2023-07-24 16:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ToArray converts the iterator to an array
|
2024-02-12 10:33:42 +01:00
|
|
|
func ToArray[GU ~func() O.Option[P.Pair[GU, U]], US ~[]U, U any](u GU) US {
|
2023-07-24 16:43:07 +02:00
|
|
|
return Reduce[GU](A.Append[US], A.Empty[US]())(u)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Map[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) V, U, V any](f FCT) func(ma GU) GV {
|
2023-07-24 16:43:07 +02:00
|
|
|
// pre-declare to avoid cyclic reference
|
2024-02-12 10:33:42 +01:00
|
|
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
2023-07-24 16:43:07 +02:00
|
|
|
|
|
|
|
recurse := func(ma GU) GV {
|
|
|
|
return F.Nullary2(
|
|
|
|
ma,
|
|
|
|
m,
|
|
|
|
)
|
|
|
|
}
|
2023-09-19 10:21:16 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
m = O.Map(P.BiMap(recurse, f))
|
2023-07-24 16:43:07 +02:00
|
|
|
|
|
|
|
return recurse
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func MonadMap[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) V) GV {
|
2023-07-24 16:43:07 +02:00
|
|
|
return Map[GV, GU](f)(ma)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func concat[GU ~func() O.Option[P.Pair[GU, U]], U any](right, left GU) GU {
|
|
|
|
var m func(ma O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GU, U]]
|
2023-07-24 16:43:07 +02:00
|
|
|
|
|
|
|
recurse := func(left GU) GU {
|
|
|
|
return F.Nullary2(left, m)
|
|
|
|
}
|
|
|
|
|
|
|
|
m = O.Fold(
|
|
|
|
right,
|
|
|
|
F.Flow2(
|
2024-02-12 10:33:42 +01:00
|
|
|
P.BiMap(recurse, F.Identity[U]),
|
|
|
|
O.Some[P.Pair[GU, U]],
|
2023-07-24 16:43:07 +02:00
|
|
|
))
|
|
|
|
|
|
|
|
return recurse(left)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Chain[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(U) GV) func(GU) GV {
|
2023-07-24 16:43:07 +02:00
|
|
|
// pre-declare to avoid cyclic reference
|
2024-02-12 10:33:42 +01:00
|
|
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
2023-07-24 16:43:07 +02:00
|
|
|
|
|
|
|
recurse := func(ma GU) GV {
|
|
|
|
return F.Nullary2(
|
|
|
|
ma,
|
|
|
|
m,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
m = O.Chain(
|
|
|
|
F.Flow3(
|
2024-02-12 10:33:42 +01:00
|
|
|
P.BiMap(recurse, f),
|
|
|
|
P.Paired(concat[GV]),
|
|
|
|
func(v GV) O.Option[P.Pair[GV, V]] {
|
2023-07-24 16:43:07 +02:00
|
|
|
return v()
|
|
|
|
},
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
return recurse
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func MonadChain[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) GV) GV {
|
2023-07-24 16:43:07 +02:00
|
|
|
return Chain[GV, GU](f)(ma)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func MonadChainFirst[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU, f func(U) GV) GU {
|
2024-02-06 21:35:33 +01:00
|
|
|
return C.MonadChainFirst(
|
|
|
|
MonadChain[GU, GU, U, U],
|
|
|
|
MonadMap[GU, GV, V, U],
|
|
|
|
ma,
|
|
|
|
f,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func ChainFirst[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](f func(U) GV) func(GU) GU {
|
2024-02-06 21:35:33 +01:00
|
|
|
return C.ChainFirst(
|
|
|
|
Chain[GU, GU, U, U],
|
|
|
|
Map[GU, GV, func(V) U, V, U],
|
|
|
|
f,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Flatten[GV ~func() O.Option[P.Pair[GV, GU]], GU ~func() O.Option[P.Pair[GU, U]], U any](ma GV) GU {
|
2023-07-24 16:43:07 +02:00
|
|
|
return MonadChain(ma, F.Identity[GU])
|
|
|
|
}
|
|
|
|
|
2023-08-04 17:12:24 +02:00
|
|
|
// MakeBy returns an [Iterator] with an infinite number of elements initialized with `f(i)`
|
2024-02-12 10:33:42 +01:00
|
|
|
func MakeBy[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(int) U, U any](f FCT) GU {
|
2023-07-24 16:43:07 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
var m func(int) O.Option[P.Pair[GU, U]]
|
2023-07-24 16:43:07 +02:00
|
|
|
|
|
|
|
recurse := func(i int) GU {
|
2023-08-04 17:12:24 +02:00
|
|
|
return F.Nullary2(
|
|
|
|
F.Constant(i),
|
|
|
|
m,
|
|
|
|
)
|
2023-07-24 16:43:07 +02:00
|
|
|
}
|
|
|
|
|
2023-08-04 17:12:24 +02:00
|
|
|
m = F.Flow3(
|
2024-02-12 10:33:42 +01:00
|
|
|
P.Of[int],
|
|
|
|
P.BiMap(F.Flow2(
|
2023-08-04 17:12:24 +02:00
|
|
|
utils.Inc,
|
|
|
|
recurse),
|
|
|
|
f),
|
2024-02-12 10:33:42 +01:00
|
|
|
O.Of[P.Pair[GU, U]],
|
2023-07-24 16:43:07 +02:00
|
|
|
)
|
|
|
|
|
2023-07-25 17:34:32 +02:00
|
|
|
// bootstrap
|
2023-07-24 16:43:07 +02:00
|
|
|
return recurse(0)
|
|
|
|
}
|
|
|
|
|
2023-08-04 17:12:24 +02:00
|
|
|
// Replicate creates an infinite [Iterator] containing a value.
|
2024-02-12 10:33:42 +01:00
|
|
|
func Replicate[GU ~func() O.Option[P.Pair[GU, U]], U any](a U) GU {
|
2023-08-04 17:12:24 +02:00
|
|
|
return MakeBy[GU](F.Constant1[int](a))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Repeat creates an [Iterator] containing a value repeated the specified number of times.
|
|
|
|
// Alias of [Replicate] combined with [Take]
|
2024-02-12 10:33:42 +01:00
|
|
|
func Repeat[GU ~func() O.Option[P.Pair[GU, U]], U any](n int, a U) GU {
|
2023-08-04 17:12:24 +02:00
|
|
|
return F.Pipe2(
|
|
|
|
a,
|
|
|
|
Replicate[GU],
|
|
|
|
Take[GU](n),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Count creates an [Iterator] containing a consecutive sequence of integers starting with the provided start value
|
2024-02-12 10:33:42 +01:00
|
|
|
func Count[GU ~func() O.Option[P.Pair[GU, int]]](start int) GU {
|
2023-08-04 17:12:24 +02:00
|
|
|
return MakeBy[GU](N.Add(start))
|
2023-07-24 16:43:07 +02:00
|
|
|
}
|
2023-07-25 17:34:32 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func FilterMap[GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) O.Option[V], U, V any](f FCT) func(ma GU) GV {
|
2023-07-25 17:34:32 +02:00
|
|
|
// pre-declare to avoid cyclic reference
|
2024-02-12 10:33:42 +01:00
|
|
|
var m func(O.Option[P.Pair[GU, U]]) O.Option[P.Pair[GV, V]]
|
2023-07-25 17:34:32 +02:00
|
|
|
|
|
|
|
recurse := func(ma GU) GV {
|
|
|
|
return F.Nullary2(
|
|
|
|
ma,
|
|
|
|
m,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
m = O.Fold(
|
|
|
|
Empty[GV](),
|
2024-02-12 10:33:42 +01:00
|
|
|
func(t P.Pair[GU, U]) O.Option[P.Pair[GV, V]] {
|
2023-11-10 13:46:10 +01:00
|
|
|
r := recurse(Next(t))
|
|
|
|
return O.MonadFold(f(Current(t)), r, F.Flow2(
|
2024-02-12 10:33:42 +01:00
|
|
|
F.Bind1st(P.MakePair[GV, V], r),
|
|
|
|
O.Some[P.Pair[GV, V]],
|
2023-07-25 17:34:32 +02:00
|
|
|
))
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
return recurse
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Filter[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) bool, U any](f FCT) func(ma GU) GU {
|
2023-07-25 17:34:32 +02:00
|
|
|
return FilterMap[GU, GU](O.FromPredicate(f))
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Ap[GUV ~func() O.Option[P.Pair[GUV, func(U) V]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](ma GU) func(fab GUV) GV {
|
2023-07-25 17:34:32 +02:00
|
|
|
return Chain[GV, GUV](F.Bind1st(MonadMap[GV, GU], ma))
|
|
|
|
}
|
2023-07-27 22:39:38 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func MonadAp[GUV ~func() O.Option[P.Pair[GUV, func(U) V]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], U, V any](fab GUV, ma GU) GV {
|
2023-07-27 22:39:38 +02:00
|
|
|
return Ap[GUV, GV, GU](ma)(fab)
|
|
|
|
}
|
2023-08-10 11:46:30 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func FilterChain[GVV ~func() O.Option[P.Pair[GVV, GV]], GV ~func() O.Option[P.Pair[GV, V]], GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) O.Option[GV], U, V any](f FCT) func(ma GU) GV {
|
2023-08-10 11:46:30 +02:00
|
|
|
return F.Flow2(
|
|
|
|
FilterMap[GVV, GU](f),
|
|
|
|
Flatten[GVV],
|
|
|
|
)
|
|
|
|
}
|
2023-08-10 18:08:11 +02:00
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func FoldMap[GU ~func() O.Option[P.Pair[GU, U]], FCT ~func(U) V, U, V any](m M.Monoid[V]) func(FCT) func(ma GU) V {
|
2023-08-10 18:08:11 +02:00
|
|
|
return func(f FCT) func(ma GU) V {
|
|
|
|
return Reduce[GU](func(cur V, a U) V {
|
|
|
|
return m.Concat(cur, f(a))
|
|
|
|
}, m.Empty())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-12 10:33:42 +01:00
|
|
|
func Fold[GU ~func() O.Option[P.Pair[GU, U]], U any](m M.Monoid[U]) func(ma GU) U {
|
2023-08-10 18:08:11 +02:00
|
|
|
return Reduce[GU](m.Concat, m.Empty())
|
|
|
|
}
|