mirror of
https://github.com/IBM/fp-go.git
synced 2025-12-19 23:42:05 +02:00
628 lines
13 KiB
Go
628 lines
13 KiB
Go
|
|
// Copyright (c) 2023 - 2025 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 readerresult
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
F "github.com/IBM/fp-go/v2/function"
|
||
|
|
N "github.com/IBM/fp-go/v2/number"
|
||
|
|
"github.com/IBM/fp-go/v2/reader"
|
||
|
|
RES "github.com/IBM/fp-go/v2/result"
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestDoInit(t *testing.T) {
|
||
|
|
initial := SimpleState{Value: 42}
|
||
|
|
result := Do(initial)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, initial, state)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBind(t *testing.T) {
|
||
|
|
t.Run("successful bind", func(t *testing.T) {
|
||
|
|
// Effectful function that depends on context
|
||
|
|
fetchValue := func(s SimpleState) ReaderResult[int] {
|
||
|
|
return func(ctx context.Context) (int, error) {
|
||
|
|
return s.Value * 2, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
Bind(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
fetchValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("bind with error", func(t *testing.T) {
|
||
|
|
fetchValue := func(s SimpleState) ReaderResult[int] {
|
||
|
|
return func(ctx context.Context) (int, error) {
|
||
|
|
return 0, errors.New("fetch failed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
Bind(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
fetchValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
assert.Equal(t, "fetch failed", err.Error())
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLet(t *testing.T) {
|
||
|
|
// Pure function that doesn't depend on context
|
||
|
|
double := func(s SimpleState) int {
|
||
|
|
return s.Value * 2
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
Let(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
double,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLetTo(t *testing.T) {
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
LetTo(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
100,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 100, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindToInit(t *testing.T) {
|
||
|
|
getValue := func(ctx context.Context) (int, error) {
|
||
|
|
return 42, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
getValue,
|
||
|
|
BindTo(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestApS(t *testing.T) {
|
||
|
|
t.Run("successful ApS", func(t *testing.T) {
|
||
|
|
getValue := func(ctx context.Context) (int, error) {
|
||
|
|
return 100, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 42}),
|
||
|
|
ApS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
getValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 100, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("ApS with error", func(t *testing.T) {
|
||
|
|
getValue := func(ctx context.Context) (int, error) {
|
||
|
|
return 0, errors.New("failed")
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 42}),
|
||
|
|
ApS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
getValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestApSL(t *testing.T) {
|
||
|
|
lenses := MakeSimpleStateLenses()
|
||
|
|
|
||
|
|
getValue := func(ctx context.Context) (int, error) {
|
||
|
|
return 100, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 42}),
|
||
|
|
ApSL(lenses.Value, getValue),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 100, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindL(t *testing.T) {
|
||
|
|
lenses := MakeSimpleStateLenses()
|
||
|
|
|
||
|
|
// Effectful function
|
||
|
|
increment := func(v int) ReaderResult[int] {
|
||
|
|
return func(ctx context.Context) (int, error) {
|
||
|
|
return v + 1, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 41}),
|
||
|
|
BindL(lenses.Value, increment),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLetL(t *testing.T) {
|
||
|
|
lenses := MakeSimpleStateLenses()
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
LetL(lenses.Value, N.Mul(2)),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLetToL(t *testing.T) {
|
||
|
|
lenses := MakeSimpleStateLenses()
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
LetToL(lenses.Value, 42),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindReaderK(t *testing.T) {
|
||
|
|
t.Run("successful BindReaderK", func(t *testing.T) {
|
||
|
|
// Context-dependent function that doesn't return error
|
||
|
|
getFromContext := func(s SimpleState) reader.Reader[context.Context, int] {
|
||
|
|
return func(ctx context.Context) int {
|
||
|
|
if val := ctx.Value("multiplier"); val != nil {
|
||
|
|
return s.Value * val.(int)
|
||
|
|
}
|
||
|
|
return s.Value
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
BindReaderK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
getFromContext,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
ctx := context.WithValue(context.Background(), "multiplier", 2)
|
||
|
|
state, err := result(ctx)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindEitherK(t *testing.T) {
|
||
|
|
t.Run("successful BindEitherK", func(t *testing.T) {
|
||
|
|
// Pure function returning Result
|
||
|
|
validate := func(s SimpleState) RES.Result[int] {
|
||
|
|
if s.Value > 0 {
|
||
|
|
return RES.Of(s.Value * 2)
|
||
|
|
}
|
||
|
|
return RES.Left[int](errors.New("value must be positive"))
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
BindEitherK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
validate,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("BindEitherK with error", func(t *testing.T) {
|
||
|
|
validate := func(s SimpleState) RES.Result[int] {
|
||
|
|
return RES.Left[int](errors.New("validation failed"))
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
BindEitherK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
validate,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
assert.Equal(t, "validation failed", err.Error())
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindResultK(t *testing.T) {
|
||
|
|
t.Run("successful BindResultK", func(t *testing.T) {
|
||
|
|
// Pure function returning (value, error)
|
||
|
|
parse := func(s SimpleState) (int, error) {
|
||
|
|
return s.Value * 2, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
BindResultK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
parse,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("BindResultK with error", func(t *testing.T) {
|
||
|
|
parse := func(s SimpleState) (int, error) {
|
||
|
|
return 0, errors.New("parse failed")
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{Value: 21}),
|
||
|
|
BindResultK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
parse,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
assert.Equal(t, "parse failed", err.Error())
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindToReader(t *testing.T) {
|
||
|
|
getFromContext := func(ctx context.Context) int {
|
||
|
|
if val := ctx.Value("value"); val != nil {
|
||
|
|
return val.(int)
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
getFromContext,
|
||
|
|
BindToReader(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
|
||
|
|
ctx := context.WithValue(context.Background(), "value", 42)
|
||
|
|
state, err := result(ctx)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindToEither(t *testing.T) {
|
||
|
|
t.Run("successful BindToEither", func(t *testing.T) {
|
||
|
|
resultValue := RES.Of(42)
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
resultValue,
|
||
|
|
BindToEither(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("BindToEither with error", func(t *testing.T) {
|
||
|
|
resultValue := RES.Left[int](errors.New("failed"))
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
resultValue,
|
||
|
|
BindToEither(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBindToResult(t *testing.T) {
|
||
|
|
t.Run("successful BindToResult", func(t *testing.T) {
|
||
|
|
value, err := 42, error(nil)
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
BindToResult(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
func(f func(int, error) ReaderResult[SimpleState]) ReaderResult[SimpleState] {
|
||
|
|
return f(value, err)
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
state, resultErr := result(context.Background())
|
||
|
|
assert.NoError(t, resultErr)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("BindToResult with error", func(t *testing.T) {
|
||
|
|
value, err := 0, errors.New("failed")
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
BindToResult(func(v int) SimpleState {
|
||
|
|
return SimpleState{Value: v}
|
||
|
|
}),
|
||
|
|
func(f func(int, error) ReaderResult[SimpleState]) ReaderResult[SimpleState] {
|
||
|
|
return f(value, err)
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
_, resultErr := result(context.Background())
|
||
|
|
assert.Error(t, resultErr)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestApReaderS(t *testing.T) {
|
||
|
|
getFromContext := func(ctx context.Context) int {
|
||
|
|
if val := ctx.Value("value"); val != nil {
|
||
|
|
return val.(int)
|
||
|
|
}
|
||
|
|
return 0
|
||
|
|
}
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
ApReaderS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
getFromContext,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
ctx := context.WithValue(context.Background(), "value", 42)
|
||
|
|
state, err := result(ctx)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestApResultS(t *testing.T) {
|
||
|
|
t.Run("successful ApResultS", func(t *testing.T) {
|
||
|
|
value, err := 42, error(nil)
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
func(rr ReaderResult[SimpleState]) ReaderResult[SimpleState] {
|
||
|
|
return F.Pipe1(
|
||
|
|
rr,
|
||
|
|
ApResultS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
)(value, err),
|
||
|
|
)
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
state, resultErr := result(context.Background())
|
||
|
|
assert.NoError(t, resultErr)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("ApResultS with error", func(t *testing.T) {
|
||
|
|
value, err := 0, errors.New("failed")
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
func(rr ReaderResult[SimpleState]) ReaderResult[SimpleState] {
|
||
|
|
return F.Pipe1(
|
||
|
|
rr,
|
||
|
|
ApResultS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
)(value, err),
|
||
|
|
)
|
||
|
|
},
|
||
|
|
)
|
||
|
|
|
||
|
|
_, resultErr := result(context.Background())
|
||
|
|
assert.Error(t, resultErr)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestApEitherS(t *testing.T) {
|
||
|
|
t.Run("successful ApEitherS", func(t *testing.T) {
|
||
|
|
resultValue := RES.Of(42)
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
ApEitherS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
resultValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
})
|
||
|
|
|
||
|
|
t.Run("ApEitherS with error", func(t *testing.T) {
|
||
|
|
resultValue := RES.Left[int](errors.New("failed"))
|
||
|
|
|
||
|
|
result := F.Pipe1(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
ApEitherS(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
resultValue,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
_, err := result(context.Background())
|
||
|
|
assert.Error(t, err)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestComplexPipeline(t *testing.T) {
|
||
|
|
lenses := MakeSimpleStateLenses()
|
||
|
|
|
||
|
|
// Complex pipeline combining multiple operations
|
||
|
|
result := F.Pipe3(
|
||
|
|
Do(SimpleState{}),
|
||
|
|
LetToL(lenses.Value, 10),
|
||
|
|
LetL(lenses.Value, N.Mul(2)),
|
||
|
|
BindResultK(
|
||
|
|
func(v int) func(SimpleState) SimpleState {
|
||
|
|
return func(s SimpleState) SimpleState {
|
||
|
|
s.Value = v
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
},
|
||
|
|
func(s SimpleState) (int, error) {
|
||
|
|
return s.Value + 22, nil
|
||
|
|
},
|
||
|
|
),
|
||
|
|
)
|
||
|
|
|
||
|
|
state, err := result(context.Background())
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 42, state.Value)
|
||
|
|
}
|