mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
@@ -52,6 +52,10 @@ func MonadMapRef[A, B any](as []A, f func(a *A) B) []B {
|
||||
return bs
|
||||
}
|
||||
|
||||
func MapWithIndex[A, B any](f func(int, A) B) func([]A) []B {
|
||||
return G.MapWithIndex[[]A, []B](f)
|
||||
}
|
||||
|
||||
func Map[A, B any](f func(a A) B) func([]A) []B {
|
||||
return F.Bind2nd(MonadMap[A, B], f)
|
||||
}
|
||||
@@ -300,6 +304,11 @@ func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
||||
return G.FoldMap[[]A](m)
|
||||
}
|
||||
|
||||
// FoldMapWithIndex maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMapWithIndex[A, B any](m M.Monoid[B]) func(func(int, A) B) func([]A) B {
|
||||
return G.FoldMapWithIndex[[]A](m)
|
||||
}
|
||||
|
||||
// Fold folds the array using the provided Monoid.
|
||||
func Fold[A any](m M.Monoid[A]) func([]A) A {
|
||||
return G.Fold[[]A](m)
|
||||
|
@@ -118,6 +118,14 @@ func Map[GA ~[]A, GB ~[]B, A, B any](f func(a A) B) func(GA) GB {
|
||||
return F.Bind2nd(MonadMap[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
func MonadMapWithIndex[GA ~[]A, GB ~[]B, A, B any](as GA, f func(int, A) B) GB {
|
||||
return array.MonadMapWithIndex[GA, GB](as, f)
|
||||
}
|
||||
|
||||
func MapWithIndex[GA ~[]A, GB ~[]B, A, B any](f func(int, A) B) func(GA) GB {
|
||||
return F.Bind2nd(MonadMapWithIndex[GA, GB, A, B], f)
|
||||
}
|
||||
|
||||
func Size[GA ~[]A, A any](as GA) int {
|
||||
return len(as)
|
||||
}
|
||||
@@ -242,6 +250,16 @@ func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
}
|
||||
}
|
||||
|
||||
func FoldMapWithIndex[AS ~[]A, A, B any](m M.Monoid[B]) func(func(int, A) B) func(AS) B {
|
||||
return func(f func(int, A) B) func(AS) B {
|
||||
return func(as AS) B {
|
||||
return array.ReduceWithIndex(as, func(idx int, cur B, a A) B {
|
||||
return m.Concat(cur, f(idx, a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Fold[AS ~[]A, A any](m M.Monoid[A]) func(AS) A {
|
||||
return func(as AS) A {
|
||||
return array.Reduce(as, m.Concat, m.Empty())
|
||||
|
@@ -18,6 +18,7 @@ package array
|
||||
import (
|
||||
"github.com/IBM/fp-go/internal/array"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
|
||||
func concat[T any](left, right []T) []T {
|
||||
@@ -40,6 +41,10 @@ func Monoid[T any]() M.Monoid[[]T] {
|
||||
return M.MakeMonoid(concat[T], Empty[T]())
|
||||
}
|
||||
|
||||
func Semigroup[T any]() S.Semigroup[[]T] {
|
||||
return S.MakeSemigroup(concat[T])
|
||||
}
|
||||
|
||||
func addLen[A any](count int, data []A) int {
|
||||
return count + len(data)
|
||||
}
|
||||
|
89
di/erasure/injector.go
Normal file
89
di/erasure/injector.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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 erasure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
I "github.com/IBM/fp-go/identity"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
R "github.com/IBM/fp-go/record"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
func providerToEntry(p Provider) T.Tuple2[string, ProviderFactory] {
|
||||
return T.MakeTuple2(p.Provides().Id(), p.Factory())
|
||||
}
|
||||
|
||||
func missingProviderError(name string) func() IOE.IOEither[error, any] {
|
||||
return func() IOE.IOEither[error, any] {
|
||||
return IOE.Left[any](fmt.Errorf("No provider for dependency [%s]", name))
|
||||
}
|
||||
}
|
||||
|
||||
func MakeInjector(providers []Provider) InjectableFactory {
|
||||
|
||||
type Result = IOE.IOEither[error, any]
|
||||
|
||||
// provide a mapping for all providers
|
||||
factoryById := F.Pipe2(
|
||||
providers,
|
||||
A.Map(providerToEntry),
|
||||
R.FromEntries[string, ProviderFactory],
|
||||
)
|
||||
// the resolved map
|
||||
var resolved = R.Empty[string, Result]()
|
||||
// the callback
|
||||
var injFct InjectableFactory
|
||||
|
||||
// lazy initialization, so we can cross reference it
|
||||
injFct = func(token Token) Result {
|
||||
|
||||
hit := F.Pipe3(
|
||||
token,
|
||||
Token.Id,
|
||||
R.Lookup[Result, string],
|
||||
I.Ap[O.Option[Result]](resolved),
|
||||
)
|
||||
|
||||
provFct := F.Pipe2(
|
||||
token,
|
||||
T.Replicate2[Token],
|
||||
T.Map2(F.Flow3(
|
||||
Token.Id,
|
||||
R.Lookup[ProviderFactory, string],
|
||||
I.Ap[O.Option[ProviderFactory]](factoryById),
|
||||
), F.Flow2(
|
||||
Token.String,
|
||||
missingProviderError,
|
||||
)),
|
||||
)
|
||||
|
||||
x := F.Pipe4(
|
||||
token,
|
||||
Token.Id,
|
||||
R.Lookup[Result, string],
|
||||
I.Ap[O.Option[Result]](resolved),
|
||||
O.GetOrElse(F.Flow2()),
|
||||
)
|
||||
}
|
||||
|
||||
return injFct
|
||||
}
|
167
di/erasure/provider.go
Normal file
167
di/erasure/provider.go
Normal file
@@ -0,0 +1,167 @@
|
||||
// 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 erasure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
E "github.com/IBM/fp-go/either"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
IO "github.com/IBM/fp-go/io"
|
||||
IOG "github.com/IBM/fp-go/io/generic"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
RIOE "github.com/IBM/fp-go/readerioeither"
|
||||
R "github.com/IBM/fp-go/record"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
type InjectableFactory = RIOE.ReaderIOEither[Token, error, any]
|
||||
type ProviderFactory = RIOE.ReaderIOEither[InjectableFactory, error, any]
|
||||
|
||||
type Provider interface {
|
||||
fmt.Stringer
|
||||
Provides() Token
|
||||
Factory() ProviderFactory
|
||||
}
|
||||
|
||||
type provider struct {
|
||||
provides Token
|
||||
factory ProviderFactory
|
||||
}
|
||||
|
||||
func (p *provider) Provides() Token {
|
||||
return p.provides
|
||||
}
|
||||
|
||||
func (p *provider) Factory() ProviderFactory {
|
||||
return p.factory
|
||||
}
|
||||
|
||||
func (p *provider) String() string {
|
||||
return fmt.Sprintf("Provider for [%s]", p.provides)
|
||||
}
|
||||
|
||||
func MakeProvider(token Token, fct ProviderFactory) Provider {
|
||||
return &provider{token, fct}
|
||||
}
|
||||
|
||||
func mapFromToken(idx int, token Token) map[TokenType]map[int]int {
|
||||
return R.Singleton(token.Type(), R.Singleton(idx, idx))
|
||||
}
|
||||
|
||||
var mergeTokenMaps = R.UnionMonoid[TokenType](R.UnionLastSemigroup[int, int]())
|
||||
var foldDeps = A.FoldMapWithIndex[Token](mergeTokenMaps)(mapFromToken)
|
||||
|
||||
var lookupMandatory = R.Lookup[map[int]int](Mandatory)
|
||||
var lookupOption = R.Lookup[map[int]int](Option)
|
||||
|
||||
type Mapping = map[TokenType]map[int]int
|
||||
|
||||
func getAt[T any](ar []T) func(idx int) T {
|
||||
return func(idx int) T {
|
||||
return ar[idx]
|
||||
}
|
||||
}
|
||||
|
||||
func handleMandatory(mp Mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, map[int]any] {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, any], IOE.Of[error, map[int]any])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, map[int]any] {
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupMandatory,
|
||||
O.Fold(
|
||||
onNone,
|
||||
IOE.TraverseRecord[int](getAt(res)),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func handleOption(mp Mapping) func(res []IOE.IOEither[error, any]) IO.IO[map[int]O.Option[any]] {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, O.Option[any]], IO.Of[map[int]O.Option[any]])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) IO.IO[map[int]O.Option[any]] {
|
||||
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupOption,
|
||||
O.Fold(
|
||||
onNone,
|
||||
F.Flow2(
|
||||
IOG.TraverseRecord[IO.IO[map[int]E.Either[error, any]], map[int]int](getAt(res)),
|
||||
IO.Map(R.Map[int](E.ToOption[error, any])),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func mergeArguments(count int) func(
|
||||
mandatory IOE.IOEither[error, map[int]any],
|
||||
optonal IO.IO[map[int]O.Option[any]],
|
||||
) IOE.IOEither[error, []any] {
|
||||
|
||||
optMapToAny := R.Map[int](F.ToAny[O.Option[any]])
|
||||
mergeMaps := R.UnionLastMonoid[int, any]()
|
||||
|
||||
return func(
|
||||
mandatory IOE.IOEither[error, map[int]any],
|
||||
optional IO.IO[map[int]O.Option[any]],
|
||||
) IOE.IOEither[error, []any] {
|
||||
|
||||
return F.Pipe1(
|
||||
IOE.SequenceT2(mandatory, IOE.FromIO[error](optional)),
|
||||
IOE.Map[error](T.Tupled2(func(mnd map[int]any, opt map[int]O.Option[any]) []any {
|
||||
// merge all parameters
|
||||
merged := mergeMaps.Concat(mnd, optMapToAny(opt))
|
||||
|
||||
return R.ReduceWithIndex(func(idx int, res []any, value any) []any {
|
||||
res[idx] = value
|
||||
return res
|
||||
}, make([]any, count))(merged)
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeProviderFactory(
|
||||
deps []Token,
|
||||
fct func(param ...any) IOE.IOEither[error, any]) ProviderFactory {
|
||||
|
||||
mapping := foldDeps(deps)
|
||||
|
||||
mandatory := handleMandatory(mapping)
|
||||
optional := handleOption(mapping)
|
||||
|
||||
merge := mergeArguments(A.Size(deps))
|
||||
|
||||
f := F.Unvariadic0(fct)
|
||||
|
||||
return func(inj InjectableFactory) IOE.IOEither[error, any] {
|
||||
// resolve all dependencies
|
||||
resolved := A.MonadMap(deps, inj)
|
||||
// resolve dependencies
|
||||
return F.Pipe1(
|
||||
merge(mandatory(resolved), optional(resolved)),
|
||||
IOE.Chain(f),
|
||||
)
|
||||
}
|
||||
}
|
33
di/erasure/token.go
Normal file
33
di/erasure/token.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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 erasure
|
||||
|
||||
import "fmt"
|
||||
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
Mandatory TokenType = iota
|
||||
Option
|
||||
IOEither
|
||||
IOOption
|
||||
)
|
||||
|
||||
type Token interface {
|
||||
fmt.Stringer
|
||||
Id() string
|
||||
Type() TokenType
|
||||
}
|
85
di/provider.go
Normal file
85
di/provider.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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 di
|
||||
|
||||
import (
|
||||
A "github.com/IBM/fp-go/array"
|
||||
DIE "github.com/IBM/fp-go/di/erasure"
|
||||
E "github.com/IBM/fp-go/either"
|
||||
ER "github.com/IBM/fp-go/erasure"
|
||||
"github.com/IBM/fp-go/errors"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
func lookupAt[T any](idx int) func(params []any) E.Either[error, T] {
|
||||
return F.Flow3(
|
||||
A.Lookup[any](idx),
|
||||
E.FromOption[any](errors.OnNone("No parameter at position %d", idx)),
|
||||
E.Chain(ER.SafeUnerase[T]),
|
||||
)
|
||||
}
|
||||
|
||||
func eraseProviderFactory0[R any](f func() IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
||||
return func(params ...any) IOE.IOEither[error, any] {
|
||||
return F.Pipe1(
|
||||
f(),
|
||||
IOE.Map[error](ER.Erase[R]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func eraseProviderFactory1[T1 any, R any](
|
||||
f func(T1) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
||||
ft := T.Tupled1(f)
|
||||
t1 := lookupAt[T1](0)
|
||||
return func(params ...any) IOE.IOEither[error, any] {
|
||||
return F.Pipe3(
|
||||
E.SequenceT1(t1(params)),
|
||||
IOE.FromEither[error, T.Tuple1[T1]],
|
||||
IOE.Chain(ft),
|
||||
IOE.Map[error](ER.Erase[R]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func MakeProvider0[R any](
|
||||
token InjectionToken[R],
|
||||
fct func() IOE.IOEither[error, R],
|
||||
) DIE.Provider {
|
||||
return DIE.MakeProvider(
|
||||
token,
|
||||
DIE.MakeProviderFactory(
|
||||
A.Empty[DIE.Token](),
|
||||
eraseProviderFactory0(fct),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func MakeProvider1[T1, R any](
|
||||
token InjectionToken[R],
|
||||
d1 InjectionToken[T1],
|
||||
fct func(T1) IOE.IOEither[error, R],
|
||||
) DIE.Provider {
|
||||
|
||||
return DIE.MakeProvider(
|
||||
token,
|
||||
DIE.MakeProviderFactory(
|
||||
A.From[DIE.Token](d1),
|
||||
eraseProviderFactory1(fct),
|
||||
),
|
||||
)
|
||||
}
|
38
di/provider_test.go
Normal file
38
di/provider_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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 di
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
)
|
||||
|
||||
func staticValue(value string) func() IOE.IOEither[error, string] {
|
||||
return F.Constant(IOE.Of[error](value))
|
||||
}
|
||||
|
||||
var (
|
||||
INJ_KEY1 = MakeToken[string]("INJ_KEY1")
|
||||
INJ_KEY2 = MakeToken[string]("INJ_KEY2")
|
||||
)
|
||||
|
||||
func TestSimpleProvider(t *testing.T) {
|
||||
p1 := MakeProvider0(INJ_KEY1, staticValue("Carsten"))
|
||||
|
||||
fmt.Println(p1)
|
||||
}
|
105
di/token.go
Normal file
105
di/token.go
Normal file
@@ -0,0 +1,105 @@
|
||||
// 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 di
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
DIE "github.com/IBM/fp-go/di/erasure"
|
||||
IO "github.com/IBM/fp-go/io"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
IOO "github.com/IBM/fp-go/iooption"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
type Token[T any] interface {
|
||||
DIE.Token
|
||||
ToType(any) O.Option[T]
|
||||
}
|
||||
|
||||
type InjectionToken[T any] interface {
|
||||
Token[T]
|
||||
Option() Token[O.Option[T]]
|
||||
IOEither() Token[IOE.IOEither[error, T]]
|
||||
IOOption() Token[IOO.IOOption[T]]
|
||||
}
|
||||
|
||||
func makeId() IO.IO[string] {
|
||||
var count int64
|
||||
return func() string {
|
||||
return strconv.FormatInt(atomic.AddInt64(&count, 1), 16)
|
||||
}
|
||||
}
|
||||
|
||||
var genId = makeId()
|
||||
|
||||
type token[T any] struct {
|
||||
name string
|
||||
id string
|
||||
typ DIE.TokenType
|
||||
}
|
||||
|
||||
func (t *token[T]) Id() string {
|
||||
return t.id
|
||||
}
|
||||
|
||||
func (t *token[T]) Type() DIE.TokenType {
|
||||
return t.typ
|
||||
}
|
||||
|
||||
func (t *token[T]) ToType(value any) O.Option[T] {
|
||||
return O.ToType[T](value)
|
||||
}
|
||||
|
||||
func (t *token[T]) String() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func makeToken[T any](name string, id string, typ DIE.TokenType) Token[T] {
|
||||
return &token[T]{name, id, typ}
|
||||
}
|
||||
|
||||
type injectionToken[T any] struct {
|
||||
token[T]
|
||||
option Token[O.Option[T]]
|
||||
ioeither Token[IOE.IOEither[error, T]]
|
||||
iooption Token[IOO.IOOption[T]]
|
||||
}
|
||||
|
||||
func (i *injectionToken[T]) Option() Token[O.Option[T]] {
|
||||
return i.option
|
||||
}
|
||||
|
||||
func (i *injectionToken[T]) IOEither() Token[IOE.IOEither[error, T]] {
|
||||
return i.ioeither
|
||||
}
|
||||
|
||||
func (i *injectionToken[T]) IOOption() Token[IOO.IOOption[T]] {
|
||||
return i.iooption
|
||||
}
|
||||
|
||||
// MakeToken create a unique injection token for a specific type
|
||||
func MakeToken[T any](name string) InjectionToken[T] {
|
||||
id := genId()
|
||||
return &injectionToken[T]{
|
||||
token[T]{name, id, DIE.Mandatory},
|
||||
makeToken[O.Option[T]](fmt.Sprintf("Option[%s]", name), id, DIE.Option),
|
||||
makeToken[IOE.IOEither[error, T]](fmt.Sprintf("IOEither[%s]", name), id, DIE.IOEither),
|
||||
makeToken[IOO.IOOption[T]](fmt.Sprintf("IOOption[%s]", name), id, DIE.IOOption),
|
||||
}
|
||||
}
|
@@ -16,6 +16,8 @@
|
||||
package erasure
|
||||
|
||||
import (
|
||||
E "github.com/IBM/fp-go/either"
|
||||
"github.com/IBM/fp-go/errors"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
)
|
||||
|
||||
@@ -29,6 +31,15 @@ func Unerase[T any](t any) T {
|
||||
return *t.(*T)
|
||||
}
|
||||
|
||||
// SafeUnerase converts an erased variable back to its original value
|
||||
func SafeUnerase[T any](t any) E.Either[error, T] {
|
||||
return F.Pipe2(
|
||||
t,
|
||||
E.ToType[*T](errors.OnSome[any]("Value %T is not unerased")),
|
||||
E.Map[error](F.Deref[T]),
|
||||
)
|
||||
}
|
||||
|
||||
// Erase0 converts a type safe function into an erased function
|
||||
func Erase0[T1 any](f func() T1) func() any {
|
||||
return F.Nullary2(f, Erase[T1])
|
||||
|
@@ -88,6 +88,15 @@ func MonadMap[GA ~[]A, GB ~[]B, A, B any](as GA, f func(a A) B) GB {
|
||||
return bs
|
||||
}
|
||||
|
||||
func MonadMapWithIndex[GA ~[]A, GB ~[]B, A, B any](as GA, f func(idx int, a A) B) GB {
|
||||
count := len(as)
|
||||
bs := make(GB, count)
|
||||
for i := count - 1; i >= 0; i-- {
|
||||
bs[i] = f(i, as[i])
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
func ConstNil[GA ~[]A, A any]() GA {
|
||||
return (GA)(nil)
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](t
|
||||
}
|
||||
|
||||
// MonadTraverseRecord transforms a record using an IO transform an IO of a record
|
||||
func MonadTraverseRecord[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||
func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
|
||||
return RR.MonadTraverse[MA](
|
||||
Of[GBS, MB],
|
||||
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||
@@ -67,7 +67,7 @@ func MonadTraverseRecord[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B,
|
||||
}
|
||||
|
||||
// TraverseRecord transforms a record using an IO transform an IO of a record
|
||||
func TraverseRecord[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
|
||||
func TraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
|
||||
return RR.Traverse[MA](
|
||||
Of[GBS, MB],
|
||||
Map[GBS, func() func(B) MB, MB, func(B) MB],
|
||||
@@ -87,5 +87,5 @@ func TraverseRecordWithIndex[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[
|
||||
}
|
||||
|
||||
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
|
||||
return MonadTraverseRecord[GA, GAS](tas, F.Identity[GA])
|
||||
return MonadTraverseRecord[GAS](tas, F.Identity[GA])
|
||||
}
|
||||
|
@@ -41,13 +41,13 @@ func SequenceArray[A any](tas []IO[A]) IO[[]A] {
|
||||
}
|
||||
|
||||
func MonadTraverseRecord[K comparable, A, B any](tas map[K]A, f func(A) IO[B]) IO[map[K]B] {
|
||||
return G.MonadTraverseRecord[IO[B], IO[map[K]B]](tas, f)
|
||||
return G.MonadTraverseRecord[IO[map[K]B]](tas, f)
|
||||
}
|
||||
|
||||
// TraverseRecord applies a function returning an [IO] to all elements in a record and the
|
||||
// transforms this into an [IO] of that record
|
||||
func TraverseRecord[K comparable, A, B any](f func(A) IO[B]) func(map[K]A) IO[map[K]B] {
|
||||
return G.TraverseRecord[IO[B], IO[map[K]B], map[K]A](f)
|
||||
return G.TraverseRecord[IO[map[K]B], map[K]A, IO[B]](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndex applies a function returning an [IO] to all elements in a record and the
|
||||
|
@@ -41,13 +41,13 @@ func SequenceArray[A any](tas []Lazy[A]) Lazy[[]A] {
|
||||
}
|
||||
|
||||
func MonadTraverseRecord[K comparable, A, B any](tas map[K]A, f func(A) Lazy[B]) Lazy[map[K]B] {
|
||||
return G.MonadTraverseRecord[Lazy[B], Lazy[map[K]B]](tas, f)
|
||||
return G.MonadTraverseRecord[Lazy[map[K]B]](tas, f)
|
||||
}
|
||||
|
||||
// TraverseRecord applies a function returning an [IO] to all elements in a record and the
|
||||
// transforms this into an [IO] of that record
|
||||
func TraverseRecord[K comparable, A, B any](f func(A) Lazy[B]) func(map[K]A) Lazy[map[K]B] {
|
||||
return G.TraverseRecord[Lazy[B], Lazy[map[K]B], map[K]A](f)
|
||||
return G.TraverseRecord[Lazy[map[K]B], map[K]A, Lazy[B]](f)
|
||||
}
|
||||
|
||||
// TraverseRecord applies a function returning an [IO] to all elements in a record and the
|
||||
|
Reference in New Issue
Block a user