@@ -18,6 +18,7 @@ package readereither
1818import (
1919 "context"
2020
21+ L "github.com/IBM/fp-go/v2/optics/lens"
2122 G "github.com/IBM/fp-go/v2/readereither/generic"
2223)
2324
@@ -80,31 +81,31 @@ func Do[S any](
8081// )
8182func Bind [S1 , S2 , T any ](
8283 setter func (T ) func (S1 ) S2 ,
83- f func ( S1 ) ReaderEither [ T ],
84- ) func ( ReaderEither [S1 ]) ReaderEither [ S2 ] {
84+ f Kleisli [ S1 , T ],
85+ ) Kleisli [ ReaderEither [S1 ], S2 ] {
8586 return G .Bind [ReaderEither [S1 ], ReaderEither [S2 ], ReaderEither [T ], context.Context , error , S1 , S2 , T ](setter , f )
8687}
8788
8889// Let attaches the result of a computation to a context [S1] to produce a context [S2]
8990func Let [S1 , S2 , T any ](
9091 setter func (T ) func (S1 ) S2 ,
9192 f func (S1 ) T ,
92- ) func ( ReaderEither [S1 ]) ReaderEither [ S2 ] {
93+ ) Kleisli [ ReaderEither [S1 ], S2 ] {
9394 return G .Let [ReaderEither [S1 ], ReaderEither [S2 ], context.Context , error , S1 , S2 , T ](setter , f )
9495}
9596
9697// LetTo attaches the a value to a context [S1] to produce a context [S2]
9798func LetTo [S1 , S2 , T any ](
9899 setter func (T ) func (S1 ) S2 ,
99100 b T ,
100- ) func ( ReaderEither [S1 ]) ReaderEither [ S2 ] {
101+ ) Kleisli [ ReaderEither [S1 ], S2 ] {
101102 return G .LetTo [ReaderEither [S1 ], ReaderEither [S2 ], context.Context , error , S1 , S2 , T ](setter , b )
102103}
103104
104105// BindTo initializes a new state [S1] from a value [T]
105106func BindTo [S1 , T any ](
106107 setter func (T ) S1 ,
107- ) func ( ReaderEither [T ]) ReaderEither [ S1 ] {
108+ ) Kleisli [ ReaderEither [T ], S1 ] {
108109 return G.BindTo [ReaderEither [S1 ], ReaderEither [T ], context.Context , error , S1 , T ](setter )
109110}
110111
@@ -148,6 +149,161 @@ func BindTo[S1, T any](
148149func ApS [S1 , S2 , T any ](
149150 setter func (T ) func (S1 ) S2 ,
150151 fa ReaderEither [T ],
151- ) func ( ReaderEither [S1 ]) ReaderEither [ S2 ] {
152+ ) Kleisli [ ReaderEither [S1 ], S2 ] {
152153 return G .ApS [ReaderEither [S1 ], ReaderEither [S2 ], ReaderEither [T ], context.Context , error , S1 , S2 , T ](setter , fa )
153154}
155+
156+ // ApSL is a variant of ApS that uses a lens to focus on a specific field in the state.
157+ // Instead of providing a setter function, you provide a lens that knows how to get and set
158+ // the field. This is more convenient when working with nested structures.
159+ //
160+ // Parameters:
161+ // - lens: A lens that focuses on a field of type T within state S
162+ // - fa: A ReaderEither computation that produces a value of type T
163+ //
164+ // Returns:
165+ // - A function that transforms ReaderEither[S] to ReaderEither[S] by setting the focused field
166+ //
167+ // Example:
168+ //
169+ // type Person struct {
170+ // Name string
171+ // Age int
172+ // }
173+ //
174+ // ageLens := lens.MakeLens(
175+ // func(p Person) int { return p.Age },
176+ // func(p Person, a int) Person { p.Age = a; return p },
177+ // )
178+ //
179+ // getAge := func(ctx context.Context) either.Either[error, int] {
180+ // return either.Right[error](30)
181+ // }
182+ //
183+ // result := F.Pipe1(
184+ // readereither.Do(Person{Name: "Alice", Age: 25}),
185+ // readereither.ApSL(ageLens, getAge),
186+ // )
187+ func ApSL [S , T any ](
188+ lens L.Lens [S , T ],
189+ fa ReaderEither [T ],
190+ ) Kleisli [ReaderEither [S ], S ] {
191+ return ApS (lens .Set , fa )
192+ }
193+
194+ // BindL is a variant of Bind that uses a lens to focus on a specific field in the state.
195+ // It combines the lens-based field access with monadic composition, allowing you to:
196+ // 1. Extract a field value using the lens
197+ // 2. Use that value in a computation that may fail
198+ // 3. Update the field with the result
199+ //
200+ // Parameters:
201+ // - lens: A lens that focuses on a field of type T within state S
202+ // - f: A function that takes the current field value and returns a ReaderEither computation
203+ //
204+ // Returns:
205+ // - A function that transforms ReaderEither[S] to ReaderEither[S]
206+ //
207+ // Example:
208+ //
209+ // type Counter struct {
210+ // Value int
211+ // }
212+ //
213+ // valueLens := lens.MakeLens(
214+ // func(c Counter) int { return c.Value },
215+ // func(c Counter, v int) Counter { c.Value = v; return c },
216+ // )
217+ //
218+ // increment := func(v int) readereither.ReaderEither[int] {
219+ // return func(ctx context.Context) either.Either[error, int] {
220+ // if v >= 100 {
221+ // return either.Left[int](errors.New("value too large"))
222+ // }
223+ // return either.Right[error](v + 1)
224+ // }
225+ // }
226+ //
227+ // result := F.Pipe1(
228+ // readereither.Of[error](Counter{Value: 42}),
229+ // readereither.BindL(valueLens, increment),
230+ // )
231+ func BindL [S , T any ](
232+ lens L.Lens [S , T ],
233+ f Kleisli [T , T ],
234+ ) Kleisli [ReaderEither [S ], S ] {
235+ return Bind [S , S , T ](lens .Set , func (s S ) ReaderEither [T ] {
236+ return f (lens .Get (s ))
237+ })
238+ }
239+
240+ // LetL is a variant of Let that uses a lens to focus on a specific field in the state.
241+ // It applies a pure transformation to the focused field without any effects.
242+ //
243+ // Parameters:
244+ // - lens: A lens that focuses on a field of type T within state S
245+ // - f: A pure function that transforms the field value
246+ //
247+ // Returns:
248+ // - A function that transforms ReaderEither[S] to ReaderEither[S]
249+ //
250+ // Example:
251+ //
252+ // type Counter struct {
253+ // Value int
254+ // }
255+ //
256+ // valueLens := lens.MakeLens(
257+ // func(c Counter) int { return c.Value },
258+ // func(c Counter, v int) Counter { c.Value = v; return c },
259+ // )
260+ //
261+ // double := func(v int) int { return v * 2 }
262+ //
263+ // result := F.Pipe1(
264+ // readereither.Of[error](Counter{Value: 21}),
265+ // readereither.LetL(valueLens, double),
266+ // )
267+ // // result when executed will be Right(Counter{Value: 42})
268+ func LetL [S , T any ](
269+ lens L.Lens [S , T ],
270+ f func (T ) T ,
271+ ) Kleisli [ReaderEither [S ], S ] {
272+ return Let [S , S , T ](lens .Set , func (s S ) T {
273+ return f (lens .Get (s ))
274+ })
275+ }
276+
277+ // LetToL is a variant of LetTo that uses a lens to focus on a specific field in the state.
278+ // It sets the focused field to a constant value.
279+ //
280+ // Parameters:
281+ // - lens: A lens that focuses on a field of type T within state S
282+ // - b: The constant value to set
283+ //
284+ // Returns:
285+ // - A function that transforms ReaderEither[S] to ReaderEither[S]
286+ //
287+ // Example:
288+ //
289+ // type Config struct {
290+ // Debug bool
291+ // Timeout int
292+ // }
293+ //
294+ // debugLens := lens.MakeLens(
295+ // func(c Config) bool { return c.Debug },
296+ // func(c Config, d bool) Config { c.Debug = d; return c },
297+ // )
298+ //
299+ // result := F.Pipe1(
300+ // readereither.Of[error](Config{Debug: true, Timeout: 30}),
301+ // readereither.LetToL(debugLens, false),
302+ // )
303+ // // result when executed will be Right(Config{Debug: false, Timeout: 30})
304+ func LetToL [S , T any ](
305+ lens L.Lens [S , T ],
306+ b T ,
307+ ) Kleisli [ReaderEither [S ], S ] {
308+ return LetTo [S , S , T ](lens .Set , b )
309+ }
0 commit comments