mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: use endomorphism in optics
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -31,25 +31,28 @@ import (
|
||||
R "github.com/IBM/fp-go/record"
|
||||
)
|
||||
|
||||
type InjectableFactory = func(Dependency) IOE.IOEither[error, any]
|
||||
type ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]
|
||||
type (
|
||||
InjectableFactory = func(Dependency) IOE.IOEither[error, any]
|
||||
ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]
|
||||
|
||||
type paramIndex = map[int]int
|
||||
type paramValue = map[int]any
|
||||
type handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
|
||||
paramIndex = map[int]int
|
||||
paramValue = map[int]any
|
||||
handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
|
||||
mapping = map[int]paramIndex
|
||||
|
||||
type Provider interface {
|
||||
fmt.Stringer
|
||||
// Provides returns the [Dependency] implemented by this provider
|
||||
Provides() Dependency
|
||||
// Factory returns s function that can create an instance of the dependency based on an [InjectableFactory]
|
||||
Factory() ProviderFactory
|
||||
}
|
||||
Provider interface {
|
||||
fmt.Stringer
|
||||
// Provides returns the [Dependency] implemented by this provider
|
||||
Provides() Dependency
|
||||
// Factory returns s function that can create an instance of the dependency based on an [InjectableFactory]
|
||||
Factory() ProviderFactory
|
||||
}
|
||||
|
||||
type provider struct {
|
||||
provides Dependency
|
||||
factory ProviderFactory
|
||||
}
|
||||
provider struct {
|
||||
provides Dependency
|
||||
factory ProviderFactory
|
||||
}
|
||||
)
|
||||
|
||||
func (p *provider) Provides() Dependency {
|
||||
return p.provides
|
||||
@@ -72,6 +75,9 @@ func mapFromToken(idx int, token Dependency) map[int]paramIndex {
|
||||
}
|
||||
|
||||
var (
|
||||
// Empty is the empty array of providers
|
||||
Empty = A.Empty[Provider]()
|
||||
|
||||
mergeTokenMaps = R.UnionMonoid[int](R.UnionLastSemigroup[int, int]())
|
||||
foldDeps = A.FoldMapWithIndex[Dependency](mergeTokenMaps)(mapFromToken)
|
||||
mergeMaps = R.UnionLastMonoid[int, any]()
|
||||
@@ -127,15 +133,13 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type Mapping = map[int]paramIndex
|
||||
|
||||
func getAt[T any](ar []T) func(idx int) T {
|
||||
return func(idx int) T {
|
||||
return ar[idx]
|
||||
}
|
||||
}
|
||||
|
||||
func handleMapping(mp Mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
||||
func handleMapping(mp mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
||||
preFct := F.Pipe1(
|
||||
mp,
|
||||
R.Collect(func(idx int, p paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
|
30
endomorphism/curry.go
Normal file
30
endomorphism/curry.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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 endomorphism
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/endomorphism/generic"
|
||||
)
|
||||
|
||||
// Curry2 curries a binary function
|
||||
func Curry2[FCT ~func(T0, T1) T1, T0, T1 any](f FCT) func(T0) Endomorphism[T1] {
|
||||
return G.Curry2[Endomorphism[T1]](f)
|
||||
}
|
||||
|
||||
// Curry3 curries a ternary function
|
||||
func Curry3[FCT ~func(T0, T1, T2) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) Endomorphism[T2] {
|
||||
return G.Curry3[Endomorphism[T2]](f)
|
||||
}
|
36
endomorphism/generic/curry.go
Normal file
36
endomorphism/generic/curry.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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
|
||||
|
||||
// Curry2 is a duplicate of [F.Curry2] but because of the type system it's not compatible otherwise
|
||||
func Curry2[GT1 ~func(T1) T1, FCT ~func(T0, T1) T1, T0, T1 any](f FCT) func(T0) GT1 {
|
||||
return func(t0 T0) GT1 {
|
||||
return func(t1 T1) T1 {
|
||||
return f(t0, t1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Curry2 is a duplicate of [F.Curry2] but because of the type system it's not compatible otherwise
|
||||
func Curry3[GT2 ~func(T2) T2, FCT ~func(T0, T1, T2) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) GT2 {
|
||||
return func(t0 T0) func(T1) GT2 {
|
||||
return func(t1 T1) GT2 {
|
||||
return func(t2 T2) T2 {
|
||||
return f(t0, t1, t2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -58,10 +58,9 @@ var (
|
||||
|
||||
// WithValue creates a [FormBuilder] for a certain field
|
||||
func WithValue(name string) func(value string) Endomorphism {
|
||||
return F.Flow3(
|
||||
return F.Flow2(
|
||||
O.Of[string],
|
||||
AtValue(name).Set,
|
||||
ENDO.Of[func(url.Values) url.Values],
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -70,25 +70,15 @@ var (
|
||||
noBody = O.None[IOE.IOEither[error, []byte]]()
|
||||
|
||||
// WithMethod creates a [BuilderBuilder] for a certain method
|
||||
WithMethod = F.Flow2(
|
||||
Method.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
WithMethod = Method.Set
|
||||
// WithUrl creates a [BuilderBuilder] for a certain method
|
||||
WithUrl = F.Flow2(
|
||||
Url.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
WithUrl = Url.Set
|
||||
// WithHeaders creates a [BuilderBuilder] for a set of headers
|
||||
WithHeaders = F.Flow2(
|
||||
Headers.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
WithHeaders = Headers.Set
|
||||
// WithBody creates a [BuilderBuilder] for a request body
|
||||
WithBody = F.Flow3(
|
||||
WithBody = F.Flow2(
|
||||
O.Of[IOE.IOEither[error, []byte]],
|
||||
Body.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
// WithContentType adds the content type header
|
||||
WithContentType = WithHeader("Content-Type")
|
||||
@@ -106,10 +96,9 @@ var (
|
||||
Requester = (*Builder).Requester
|
||||
|
||||
// WithoutBody creates a [BuilderBuilder] to remove the body
|
||||
WithoutBody = F.Pipe2(
|
||||
WithoutBody = F.Pipe1(
|
||||
noBody,
|
||||
Body.Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -216,7 +205,7 @@ func Header(name string) L.Lens[*Builder, O.Option[string]] {
|
||||
LZ.Map(delHeader(name)),
|
||||
)
|
||||
|
||||
return L.MakeLens[*Builder, O.Option[string]](get, func(b *Builder, value O.Option[string]) *Builder {
|
||||
return L.MakeLens(get, func(b *Builder, value O.Option[string]) *Builder {
|
||||
cpy := b.clone()
|
||||
return F.Pipe1(
|
||||
value,
|
||||
@@ -227,10 +216,9 @@ func Header(name string) L.Lens[*Builder, O.Option[string]] {
|
||||
|
||||
// WithHeader creates a [BuilderBuilder] for a certain header
|
||||
func WithHeader(name string) func(value string) Endomorphism {
|
||||
return F.Flow3(
|
||||
return F.Flow2(
|
||||
O.Of[string],
|
||||
Header(name).Set,
|
||||
ENDO.Of[func(*Builder) *Builder],
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package iso
|
||||
|
||||
import (
|
||||
EM "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
)
|
||||
|
||||
@@ -52,7 +53,7 @@ func Reverse[S, A any](sa Iso[S, A]) Iso[A, S] {
|
||||
)
|
||||
}
|
||||
|
||||
func modify[S, A any](f func(A) A, sa Iso[S, A], s S) S {
|
||||
func modify[FCT ~func(A) A, S, A any](f FCT, sa Iso[S, A], s S) S {
|
||||
return F.Pipe3(
|
||||
s,
|
||||
sa.Get,
|
||||
@@ -62,8 +63,8 @@ func modify[S, A any](f func(A) A, sa Iso[S, A], s S) S {
|
||||
}
|
||||
|
||||
// Modify applies a transformation
|
||||
func Modify[S, A any](f func(A) A) func(Iso[S, A]) func(S) S {
|
||||
return F.Curry3(modify[S, A])(f)
|
||||
func Modify[S any, FCT ~func(A) A, A any](f FCT) func(Iso[S, A]) EM.Endomorphism[S] {
|
||||
return EM.Curry3(modify[FCT, S, A])(f)
|
||||
}
|
||||
|
||||
// Wrap wraps the value
|
||||
|
@@ -16,6 +16,7 @@
|
||||
package lens
|
||||
|
||||
import (
|
||||
EM "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
I "github.com/IBM/fp-go/optics/iso"
|
||||
L "github.com/IBM/fp-go/optics/lens"
|
||||
@@ -23,10 +24,10 @@ import (
|
||||
|
||||
// IsoAsLens converts an `Iso` to a `Lens`
|
||||
func IsoAsLens[S, A any](sa I.Iso[S, A]) L.Lens[S, A] {
|
||||
return L.MakeLensCurried(sa.Get, F.Flow2(sa.ReverseGet, F.Constant1[S, S]))
|
||||
return L.MakeLensCurried(sa.Get, F.Flow2(sa.ReverseGet, F.Flow2(F.Constant1[S, S], EM.Of[func(S) S])))
|
||||
}
|
||||
|
||||
// IsoAsLensRef converts an `Iso` to a `Lens`
|
||||
func IsoAsLensRef[S, A any](sa I.Iso[*S, A]) L.Lens[*S, A] {
|
||||
return L.MakeLensRefCurried(sa.Get, F.Flow2(sa.ReverseGet, F.Constant1[*S, *S]))
|
||||
return L.MakeLensRefCurried(sa.Get, F.Flow2(sa.ReverseGet, F.Flow2(F.Constant1[*S, *S], EM.Of[func(*S) *S])))
|
||||
}
|
||||
|
@@ -17,8 +17,8 @@
|
||||
package lens
|
||||
|
||||
import (
|
||||
EM "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
I "github.com/IBM/fp-go/identity"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
@@ -26,13 +26,13 @@ type (
|
||||
// Lens is a reference to a subpart of a data type
|
||||
Lens[S, A any] struct {
|
||||
Get func(s S) A
|
||||
Set func(a A) func(S) S
|
||||
Set func(a A) EM.Endomorphism[S]
|
||||
}
|
||||
)
|
||||
|
||||
// setCopy wraps a setter for a pointer into a setter that first creates a copy before
|
||||
// modifying that copy
|
||||
func setCopy[S, A any](setter func(*S, A) *S) func(s *S, a A) *S {
|
||||
func setCopy[SET ~func(*S, A) *S, S, A any](setter SET) func(s *S, a A) *S {
|
||||
return func(s *S, a A) *S {
|
||||
copy := *s
|
||||
return setter(©, a)
|
||||
@@ -41,8 +41,8 @@ func setCopy[S, A any](setter func(*S, A) *S) func(s *S, a A) *S {
|
||||
|
||||
// setCopyCurried wraps a setter for a pointer into a setter that first creates a copy before
|
||||
// modifying that copy
|
||||
func setCopyCurried[S, A any](setter func(A) func(*S) *S) func(a A) func(*S) *S {
|
||||
return func(a A) func(*S) *S {
|
||||
func setCopyCurried[SET ~func(A) EM.Endomorphism[*S], S, A any](setter SET) func(a A) EM.Endomorphism[*S] {
|
||||
return func(a A) EM.Endomorphism[*S] {
|
||||
seta := setter(a)
|
||||
return func(s *S) *S {
|
||||
copy := *s
|
||||
@@ -51,53 +51,53 @@ func setCopyCurried[S, A any](setter func(A) func(*S) *S) func(a A) func(*S) *S
|
||||
}
|
||||
}
|
||||
|
||||
// MakeLens creates a lens based on a getter and a setter function. Make sure that the setter creates a (shallow) copy of the
|
||||
// MakeLens creates a [Lens] based on a getter and a setter function. Make sure that the setter creates a (shallow) copy of the
|
||||
// data. This happens automatically if the data is passed by value. For pointers consider to use `MakeLensRef`
|
||||
// and for other kinds of data structures that are copied by reference make sure the setter creates the copy.
|
||||
func MakeLens[S, A any](get func(S) A, set func(S, A) S) Lens[S, A] {
|
||||
return MakeLensCurried(get, F.Curry2(F.Swap(set)))
|
||||
func MakeLens[GET ~func(S) A, SET ~func(S, A) S, S, A any](get GET, set SET) Lens[S, A] {
|
||||
return MakeLensCurried(get, EM.Curry2(F.Swap(set)))
|
||||
}
|
||||
|
||||
// MakeLensCurried creates a lens based on a getter and a setter function. Make sure that the setter creates a (shallow) copy of the
|
||||
// MakeLensCurried creates a [Lens] based on a getter and a setter function. Make sure that the setter creates a (shallow) copy of the
|
||||
// data. This happens automatically if the data is passed by value. For pointers consider to use `MakeLensRef`
|
||||
// and for other kinds of data structures that are copied by reference make sure the setter creates the copy.
|
||||
func MakeLensCurried[S, A any](get func(S) A, set func(A) func(S) S) Lens[S, A] {
|
||||
func MakeLensCurried[GET ~func(S) A, SET ~func(A) EM.Endomorphism[S], S, A any](get GET, set SET) Lens[S, A] {
|
||||
return Lens[S, A]{Get: get, Set: set}
|
||||
}
|
||||
|
||||
// MakeLensRef creates a lens based on a getter and a setter function. The setter passed in does not have to create a shallow
|
||||
// MakeLensRef creates a [Lens] based on a getter and a setter function. The setter passed in does not have to create a shallow
|
||||
// copy, the implementation wraps the setter into one that copies the pointer before modifying it
|
||||
//
|
||||
// Such a lens assumes that property A of S always exists
|
||||
func MakeLensRef[S, A any](get func(*S) A, set func(*S, A) *S) Lens[*S, A] {
|
||||
// Such a [Lens] assumes that property A of S always exists
|
||||
func MakeLensRef[GET ~func(*S) A, SET func(*S, A) *S, S, A any](get GET, set SET) Lens[*S, A] {
|
||||
return MakeLens(get, setCopy(set))
|
||||
}
|
||||
|
||||
// MakeLensRefCurried creates a lens based on a getter and a setter function. The setter passed in does not have to create a shallow
|
||||
// MakeLensRefCurried creates a [Lens] based on a getter and a setter function. The setter passed in does not have to create a shallow
|
||||
// copy, the implementation wraps the setter into one that copies the pointer before modifying it
|
||||
//
|
||||
// Such a lens assumes that property A of S always exists
|
||||
func MakeLensRefCurried[S, A any](get func(*S) A, set func(A) func(*S) *S) Lens[*S, A] {
|
||||
// Such a [Lens] assumes that property A of S always exists
|
||||
func MakeLensRefCurried[S, A any](get func(*S) A, set func(A) EM.Endomorphism[*S]) Lens[*S, A] {
|
||||
return MakeLensCurried(get, setCopyCurried(set))
|
||||
}
|
||||
|
||||
// Id returns a lens implementing the identity operation
|
||||
func id[S any](creator func(get func(S) S, set func(S, S) S) Lens[S, S]) Lens[S, S] {
|
||||
// id returns a [Lens] implementing the identity operation
|
||||
func id[GET ~func(S) S, SET ~func(S, S) S, S any](creator func(get GET, set SET) Lens[S, S]) Lens[S, S] {
|
||||
return creator(F.Identity[S], F.Second[S, S])
|
||||
}
|
||||
|
||||
// Id returns a lens implementing the identity operation
|
||||
// Id returns a [Lens] implementing the identity operation
|
||||
func Id[S any]() Lens[S, S] {
|
||||
return id(MakeLens[S, S])
|
||||
return id(MakeLens[EM.Endomorphism[S], func(S, S) S])
|
||||
}
|
||||
|
||||
// IdRef returns a lens implementing the identity operation
|
||||
// IdRef returns a [Lens] implementing the identity operation
|
||||
func IdRef[S any]() Lens[*S, *S] {
|
||||
return id(MakeLensRef[S, *S])
|
||||
return id(MakeLensRef[EM.Endomorphism[*S], func(*S, *S) *S])
|
||||
}
|
||||
|
||||
// Compose combines two lenses and allows to narrow down the focus to a sub-lens
|
||||
func compose[S, A, B any](creator func(get func(S) B, set func(S, B) S) Lens[S, B], ab Lens[A, B]) func(Lens[S, A]) Lens[S, B] {
|
||||
func compose[GET ~func(S) B, SET ~func(S, B) S, S, A, B any](creator func(get GET, set SET) Lens[S, B], ab Lens[A, B]) func(Lens[S, A]) Lens[S, B] {
|
||||
abget := ab.Get
|
||||
abset := ab.Set
|
||||
return func(sa Lens[S, A]) Lens[S, B] {
|
||||
@@ -114,7 +114,7 @@ func compose[S, A, B any](creator func(get func(S) B, set func(S, B) S) Lens[S,
|
||||
|
||||
// Compose combines two lenses and allows to narrow down the focus to a sub-lens
|
||||
func Compose[S, A, B any](ab Lens[A, B]) func(Lens[S, A]) Lens[S, B] {
|
||||
return compose(MakeLens[S, B], ab)
|
||||
return compose(MakeLens[func(S) B, func(S, B) S], ab)
|
||||
}
|
||||
|
||||
// ComposeOption combines a `Lens` that returns an optional value with a `Lens` that returns a definite value
|
||||
@@ -141,7 +141,7 @@ func ComposeOption[S, B, A any](defaultA A) func(ab Lens[A, B]) func(Lens[S, O.O
|
||||
func(s S, ob O.Option[B]) S {
|
||||
return F.Pipe2(
|
||||
ob,
|
||||
O.Fold(unseta, func(b B) func(S) S {
|
||||
O.Fold(unseta, func(b B) EM.Endomorphism[S] {
|
||||
setbona := F.Flow2(
|
||||
ab.Set(b),
|
||||
seta,
|
||||
@@ -158,7 +158,7 @@ func ComposeOption[S, B, A any](defaultA A) func(ab Lens[A, B]) func(Lens[S, O.O
|
||||
),
|
||||
)
|
||||
}),
|
||||
I.Ap[S, S](s),
|
||||
EM.Ap(s),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -174,7 +174,7 @@ func ComposeOption[S, B, A any](defaultA A) func(ab Lens[A, B]) func(Lens[S, O.O
|
||||
// if the setter is called with `None[B]` and `A` does exist, 'B' is removed from 'A'
|
||||
func ComposeOptions[S, B, A any](defaultA A) func(ab Lens[A, O.Option[B]]) func(Lens[S, O.Option[A]]) Lens[S, O.Option[B]] {
|
||||
defa := F.Constant(defaultA)
|
||||
noops := F.Constant(F.Identity[S])
|
||||
noops := EM.Identity[S]
|
||||
noneb := O.None[B]()
|
||||
return func(ab Lens[A, O.Option[B]]) func(Lens[S, O.Option[A]]) Lens[S, O.Option[B]] {
|
||||
unsetb := ab.Set(noneb)
|
||||
@@ -189,15 +189,15 @@ func ComposeOptions[S, B, A any](defaultA A) func(ab Lens[A, O.Option[B]]) func(
|
||||
sa.Get,
|
||||
O.Chain(ab.Get),
|
||||
),
|
||||
func(b O.Option[B]) func(S) S {
|
||||
func(b O.Option[B]) EM.Endomorphism[S] {
|
||||
return func(s S) S {
|
||||
return O.MonadFold(b, func() func(S) S {
|
||||
return O.MonadFold(b, func() EM.Endomorphism[S] {
|
||||
return F.Pipe2(
|
||||
s,
|
||||
sa.Get,
|
||||
O.Fold(noops, F.Flow2(unsetb, seta)),
|
||||
)
|
||||
}, func(b B) func(S) S {
|
||||
}, func(b B) EM.Endomorphism[S] {
|
||||
// sets a B onto an A
|
||||
setb := F.Flow2(
|
||||
ab.Set(O.Some(b)),
|
||||
@@ -218,20 +218,20 @@ func ComposeOptions[S, B, A any](defaultA A) func(ab Lens[A, O.Option[B]]) func(
|
||||
|
||||
// Compose combines two lenses and allows to narrow down the focus to a sub-lens
|
||||
func ComposeRef[S, A, B any](ab Lens[A, B]) func(Lens[*S, A]) Lens[*S, B] {
|
||||
return compose(MakeLensRef[S, B], ab)
|
||||
return compose(MakeLensRef[func(*S) B, func(*S, B) *S], ab)
|
||||
}
|
||||
|
||||
func modify[S, A any](f func(A) A, sa Lens[S, A], s S) S {
|
||||
func modify[FCT ~func(A) A, S, A any](f FCT, sa Lens[S, A], s S) S {
|
||||
return sa.Set(f(sa.Get(s)))(s)
|
||||
}
|
||||
|
||||
// Modify changes a property of a lens by invoking a transformation function
|
||||
// Modify changes a property of a [Lens] by invoking a transformation function
|
||||
// if the transformed property has not changes, the method returns the original state
|
||||
func Modify[S, A any](f func(A) A) func(Lens[S, A]) func(S) S {
|
||||
return F.Curry3(modify[S, A])(f)
|
||||
func Modify[S any, FCT ~func(A) A, A any](f FCT) func(Lens[S, A]) EM.Endomorphism[S] {
|
||||
return EM.Curry3(modify[FCT, S, A])(f)
|
||||
}
|
||||
|
||||
func IMap[E, A, B any](ab func(A) B, ba func(B) A) func(Lens[E, A]) Lens[E, B] {
|
||||
func IMap[E any, AB ~func(A) B, BA ~func(B) A, A, B any](ab AB, ba BA) func(Lens[E, A]) Lens[E, B] {
|
||||
return func(ea Lens[E, A]) Lens[E, B] {
|
||||
return Lens[E, B]{Get: F.Flow2(ea.Get, ab), Set: F.Flow2(ba, ea.Set)}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ func IMap[E, A, B any](ab func(A) B, ba func(B) A) func(Lens[E, A]) Lens[E, B] {
|
||||
|
||||
// fromPredicate returns a `Lens` for a property accessibly as a getter and setter that can be optional
|
||||
// if the optional value is set then the nil value will be set instead
|
||||
func fromPredicate[S, A any](creator func(get func(S) O.Option[A], set func(S, O.Option[A]) S) Lens[S, O.Option[A]], pred func(A) bool, nilValue A) func(sa Lens[S, A]) Lens[S, O.Option[A]] {
|
||||
func fromPredicate[GET ~func(S) O.Option[A], SET ~func(S, O.Option[A]) S, S, A any](creator func(get GET, set SET) Lens[S, O.Option[A]], pred func(A) bool, nilValue A) func(sa Lens[S, A]) Lens[S, O.Option[A]] {
|
||||
fromPred := O.FromPredicate(pred)
|
||||
return func(sa Lens[S, A]) Lens[S, O.Option[A]] {
|
||||
fold := O.Fold(F.Bind1of1(sa.Set)(nilValue), sa.Set)
|
||||
@@ -247,7 +247,7 @@ func fromPredicate[S, A any](creator func(get func(S) O.Option[A], set func(S, O
|
||||
return F.Pipe2(
|
||||
a,
|
||||
fold,
|
||||
I.Ap[S, S](s),
|
||||
EM.Ap(s),
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -256,13 +256,13 @@ func fromPredicate[S, A any](creator func(get func(S) O.Option[A], set func(S, O
|
||||
// FromPredicate returns a `Lens` for a property accessibly as a getter and setter that can be optional
|
||||
// if the optional value is set then the nil value will be set instead
|
||||
func FromPredicate[S, A any](pred func(A) bool, nilValue A) func(sa Lens[S, A]) Lens[S, O.Option[A]] {
|
||||
return fromPredicate(MakeLens[S, O.Option[A]], pred, nilValue)
|
||||
return fromPredicate(MakeLens[func(S) O.Option[A], func(S, O.Option[A]) S], pred, nilValue)
|
||||
}
|
||||
|
||||
// FromPredicateRef returns a `Lens` for a property accessibly as a getter and setter that can be optional
|
||||
// if the optional value is set then the nil value will be set instead
|
||||
func FromPredicateRef[S, A any](pred func(A) bool, nilValue A) func(sa Lens[*S, A]) Lens[*S, O.Option[A]] {
|
||||
return fromPredicate(MakeLensRef[S, O.Option[A]], pred, nilValue)
|
||||
return fromPredicate(MakeLensRef[func(*S) O.Option[A], func(*S, O.Option[A]) *S], pred, nilValue)
|
||||
}
|
||||
|
||||
// FromPredicate returns a `Lens` for a property accessibly as a getter and setter that can be optional
|
||||
@@ -278,7 +278,7 @@ func FromNillableRef[S, A any](sa Lens[*S, *A]) Lens[*S, O.Option[*A]] {
|
||||
}
|
||||
|
||||
// fromNullableProp returns a `Lens` from a property that may be optional. The getter returns a default value for these items
|
||||
func fromNullableProp[S, A any](creator func(get func(S) A, set func(S, A) S) Lens[S, A], isNullable func(A) O.Option[A], defaultValue A) func(sa Lens[S, A]) Lens[S, A] {
|
||||
func fromNullableProp[GET ~func(S) A, SET ~func(S, A) S, S, A any](creator func(get GET, set SET) Lens[S, A], isNullable func(A) O.Option[A], defaultValue A) func(sa Lens[S, A]) Lens[S, A] {
|
||||
return func(sa Lens[S, A]) Lens[S, A] {
|
||||
return creator(F.Flow3(
|
||||
sa.Get,
|
||||
@@ -293,16 +293,16 @@ func fromNullableProp[S, A any](creator func(get func(S) A, set func(S, A) S) Le
|
||||
|
||||
// FromNullableProp returns a `Lens` from a property that may be optional. The getter returns a default value for these items
|
||||
func FromNullableProp[S, A any](isNullable func(A) O.Option[A], defaultValue A) func(sa Lens[S, A]) Lens[S, A] {
|
||||
return fromNullableProp(MakeLens[S, A], isNullable, defaultValue)
|
||||
return fromNullableProp(MakeLens[func(S) A, func(S, A) S], isNullable, defaultValue)
|
||||
}
|
||||
|
||||
// FromNullablePropRef returns a `Lens` from a property that may be optional. The getter returns a default value for these items
|
||||
func FromNullablePropRef[S, A any](isNullable func(A) O.Option[A], defaultValue A) func(sa Lens[*S, A]) Lens[*S, A] {
|
||||
return fromNullableProp(MakeLensRef[S, A], isNullable, defaultValue)
|
||||
return fromNullableProp(MakeLensRef[func(*S) A, func(*S, A) *S], isNullable, defaultValue)
|
||||
}
|
||||
|
||||
// fromFromOption returns a `Lens` from an option property. The getter returns a default value the setter will always set the some option
|
||||
func fromOption[S, A any](creator func(get func(S) A, set func(S, A) S) Lens[S, A], defaultValue A) func(sa Lens[S, O.Option[A]]) Lens[S, A] {
|
||||
func fromOption[GET ~func(S) A, SET ~func(S, A) S, S, A any](creator func(get GET, set SET) Lens[S, A], defaultValue A) func(sa Lens[S, O.Option[A]]) Lens[S, A] {
|
||||
return func(sa Lens[S, O.Option[A]]) Lens[S, A] {
|
||||
return creator(F.Flow2(
|
||||
sa.Get,
|
||||
@@ -316,10 +316,10 @@ func fromOption[S, A any](creator func(get func(S) A, set func(S, A) S) Lens[S,
|
||||
|
||||
// FromFromOption returns a `Lens` from an option property. The getter returns a default value the setter will always set the some option
|
||||
func FromOption[S, A any](defaultValue A) func(sa Lens[S, O.Option[A]]) Lens[S, A] {
|
||||
return fromOption(MakeLens[S, A], defaultValue)
|
||||
return fromOption(MakeLens[func(S) A, func(S, A) S], defaultValue)
|
||||
}
|
||||
|
||||
// FromFromOptionRef returns a `Lens` from an option property. The getter returns a default value the setter will always set the some option
|
||||
func FromOptionRef[S, A any](defaultValue A) func(sa Lens[*S, O.Option[A]]) Lens[*S, A] {
|
||||
return fromOption(MakeLensRef[S, A], defaultValue)
|
||||
return fromOption(MakeLensRef[func(*S) A, func(*S, A) *S], defaultValue)
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
package optional
|
||||
|
||||
import (
|
||||
EM "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
@@ -25,12 +26,12 @@ import (
|
||||
// Optional is an optional reference to a subpart of a data type
|
||||
type Optional[S, A any] struct {
|
||||
GetOption func(s S) O.Option[A]
|
||||
Set func(a A) func(S) S
|
||||
Set func(a A) EM.Endomorphism[S]
|
||||
}
|
||||
|
||||
// setCopy wraps a setter for a pointer into a setter that first creates a copy before
|
||||
// modifying that copy
|
||||
func setCopy[S, A any](setter func(*S, A) *S) func(s *S, a A) *S {
|
||||
func setCopy[SET ~func(*S, A) *S, S, A any](setter SET) func(s *S, a A) *S {
|
||||
return func(s *S, a A) *S {
|
||||
copy := *s
|
||||
return setter(©, a)
|
||||
@@ -41,7 +42,7 @@ func setCopy[S, A any](setter func(*S, A) *S) func(s *S, a A) *S {
|
||||
// data. This happens automatically if the data is passed by value. For pointers consider to use `MakeOptionalRef`
|
||||
// and for other kinds of data structures that are copied by reference make sure the setter creates the copy.
|
||||
func MakeOptional[S, A any](get func(S) O.Option[A], set func(S, A) S) Optional[S, A] {
|
||||
return Optional[S, A]{GetOption: get, Set: F.Curry2(F.Swap(set))}
|
||||
return Optional[S, A]{GetOption: get, Set: EM.Curry2(F.Swap(set))}
|
||||
}
|
||||
|
||||
// MakeOptionalRef creates an Optional based on a getter and a setter function. The setter passed in does not have to create a shallow
|
||||
@@ -168,7 +169,7 @@ func ichain[S, A, B any](sa Optional[S, A], ab func(A) O.Option[B], ba func(B) O
|
||||
return MakeOptional(
|
||||
F.Flow2(sa.GetOption, O.Chain(ab)),
|
||||
func(s S, b B) S {
|
||||
return O.MonadFold(ba(b), F.Constant(F.Identity[S]), sa.Set)(s)
|
||||
return O.MonadFold(ba(b), EM.Identity[S], sa.Set)(s)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package prism
|
||||
|
||||
import (
|
||||
EM "github.com/IBM/fp-go/endomorphism"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
@@ -86,12 +87,12 @@ func prismModify[S, A any](f func(A) A, sa Prism[S, A], s S) S {
|
||||
)
|
||||
}
|
||||
|
||||
func prismSet[S, A any](a A) func(Prism[S, A]) func(S) S {
|
||||
return F.Curry3(prismModify[S, A])(F.Constant1[A](a))
|
||||
func prismSet[S, A any](a A) func(Prism[S, A]) EM.Endomorphism[S] {
|
||||
return EM.Curry3(prismModify[S, A])(F.Constant1[A](a))
|
||||
}
|
||||
|
||||
func Set[S, A any](a A) func(Prism[S, A]) func(S) S {
|
||||
return F.Curry3(prismModify[S, A])(F.Constant1[A](a))
|
||||
func Set[S, A any](a A) func(Prism[S, A]) EM.Endomorphism[S] {
|
||||
return EM.Curry3(prismModify[S, A])(F.Constant1[A](a))
|
||||
}
|
||||
|
||||
func prismSome[A any]() Prism[O.Option[A], A] {
|
||||
@@ -103,14 +104,14 @@ func Some[S, A any](soa Prism[S, O.Option[A]]) Prism[S, A] {
|
||||
return Compose[S](prismSome[A]())(soa)
|
||||
}
|
||||
|
||||
func imap[S, A, B any](sa Prism[S, A], ab func(A) B, ba func(B) A) Prism[S, B] {
|
||||
func imap[S any, AB ~func(A) B, BA ~func(B) A, A, B any](sa Prism[S, A], ab AB, ba BA) Prism[S, B] {
|
||||
return MakePrism(
|
||||
F.Flow2(sa.GetOption, O.Map(ab)),
|
||||
F.Flow2(ba, sa.ReverseGet),
|
||||
)
|
||||
}
|
||||
|
||||
func IMap[S, A, B any](ab func(A) B, ba func(B) A) func(Prism[S, A]) Prism[S, B] {
|
||||
func IMap[S any, AB ~func(A) B, BA ~func(B) A, A, B any](ab AB, ba BA) func(Prism[S, A]) Prism[S, B] {
|
||||
return func(sa Prism[S, A]) Prism[S, B] {
|
||||
return imap(sa, ab, ba)
|
||||
}
|
||||
|
Reference in New Issue
Block a user