Skip to content

Commit

Permalink
fix: use endomorphism in optics
Browse files Browse the repository at this point in the history
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
  • Loading branch information
CarstenLeue committed Dec 18, 2023
1 parent 6d043d2 commit a87de2f
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 103 deletions.
46 changes: 25 additions & 21 deletions di/erasure/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 paramIndex = map[int]int
type paramValue = map[int]any
type handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]

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
}
type (
InjectableFactory = func(Dependency) IOE.IOEither[error, any]
ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]

paramIndex = map[int]int
paramValue = map[int]any
handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
mapping = map[int]paramIndex

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
Expand All @@ -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]()
Expand Down Expand Up @@ -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] {
Expand Down
30 changes: 30 additions & 0 deletions endomorphism/curry.go
Original file line number Diff line number Diff line change
@@ -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 changes: 36 additions & 0 deletions endomorphism/generic/curry.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}
3 changes: 1 addition & 2 deletions http/form/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -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],
)
}

Expand Down
26 changes: 7 additions & 19 deletions ioeither/http/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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],
)
)

Expand Down Expand Up @@ -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,
Expand All @@ -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],
)
}

Expand Down
7 changes: 4 additions & 3 deletions optics/iso/iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package iso

import (
EM "github.com/IBM/fp-go/endomorphism"
F "github.com/IBM/fp-go/function"
)

Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions optics/iso/lens/lens.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@
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"
)

// 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])))
}
Loading

0 comments on commit a87de2f

Please sign in to comment.