mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-30 19:52:00 +02:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0064ac1c75 | ||
|
8944a66c18 | ||
|
bd0c42db01 | ||
|
e9f03e2d26 | ||
|
bb630810fc | ||
|
9ba9eaacbe | ||
|
a9f6839acd | ||
|
1b1dccc551 | ||
|
39c6108bf5 | ||
|
83e1ff30c1 | ||
|
d9dda4cfa5 | ||
|
d9b2804a7e | ||
|
c0028918ae | ||
|
cd53cb7036 | ||
|
469c60f05d |
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@@ -17,22 +17,25 @@ on:
|
||||
env:
|
||||
# Currently no way to detect automatically
|
||||
DEFAULT_BRANCH: main
|
||||
GO_VERSION: 1.20.5 # renovate: datasource=golang-version depName=golang
|
||||
GO_VERSION: 1.20.6 # renovate: datasource=golang-version depName=golang
|
||||
NODE_VERSION: 18
|
||||
DRY_RUN: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ '1.20.x', '1.21.x' ]
|
||||
steps:
|
||||
# full checkout for semantic-release
|
||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up go ${{env.GO_VERSION}}
|
||||
- name: Set up go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{env.GO_VERSION}}
|
||||
go-version: ${{ matrix.go-version }}
|
||||
-
|
||||
name: Tests
|
||||
run: |
|
||||
|
@@ -108,10 +108,16 @@ func MonadFilterMap[A, B any](fa []A, f func(a A) O.Option[B]) []B {
|
||||
return G.MonadFilterMap[[]A, []B](fa, f)
|
||||
}
|
||||
|
||||
// FilterChain maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||
func FilterMap[A, B any](f func(a A) O.Option[B]) func([]A) []B {
|
||||
return G.FilterMap[[]A, []B](f)
|
||||
}
|
||||
|
||||
// FilterChain maps an array with an iterating function that returns an [O.Option] of an array. It keeps only the Some values discarding the Nones and then flattens the result.
|
||||
func FilterChain[A, B any](f func(A) O.Option[[]B]) func([]A) []B {
|
||||
return G.FilterChain[[]A](f)
|
||||
}
|
||||
|
||||
func FilterMapRef[A, B any](pred func(a *A) bool, f func(a *A) B) func([]A) []B {
|
||||
return func(fa []A) []B {
|
||||
return filterMapRef(fa, pred, f)
|
||||
@@ -237,7 +243,7 @@ func Intercalate[A any](m M.Monoid[A]) func(A) func([]A) A {
|
||||
}
|
||||
|
||||
func Flatten[A any](mma [][]A) []A {
|
||||
return MonadChain(mma, F.Identity[[]A])
|
||||
return G.Flatten(mma)
|
||||
}
|
||||
|
||||
func Slice[A any](low, high int) func(as []A) []A {
|
||||
@@ -288,3 +294,13 @@ func SliceRight[A any](start int) func([]A) []A {
|
||||
func Copy[A any](b []A) []A {
|
||||
return G.Copy(b)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
||||
return G.FoldMap[[]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)
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
package array
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -142,3 +143,52 @@ func TestPartition(t *testing.T) {
|
||||
assert.Equal(t, T.MakeTuple2(Empty[int](), Empty[int]()), Partition(pred)(Empty[int]()))
|
||||
assert.Equal(t, T.MakeTuple2(From(1), From(3)), Partition(pred)(From(1, 3)))
|
||||
}
|
||||
|
||||
func TestFilterChain(t *testing.T) {
|
||||
src := From(1, 2, 3)
|
||||
|
||||
f := func(i int) O.Option[[]string] {
|
||||
if i%2 != 0 {
|
||||
return O.Of(From(fmt.Sprintf("a%d", i), fmt.Sprintf("b%d", i)))
|
||||
}
|
||||
return O.None[[]string]()
|
||||
}
|
||||
|
||||
res := FilterChain(f)(src)
|
||||
|
||||
assert.Equal(t, From("a1", "b1", "a3", "b3"), res)
|
||||
}
|
||||
|
||||
func TestFilterMap(t *testing.T) {
|
||||
src := From(1, 2, 3)
|
||||
|
||||
f := func(i int) O.Option[string] {
|
||||
if i%2 != 0 {
|
||||
return O.Of(fmt.Sprintf("a%d", i))
|
||||
}
|
||||
return O.None[string]()
|
||||
}
|
||||
|
||||
res := FilterMap(f)(src)
|
||||
|
||||
assert.Equal(t, From("a1", "a3"), res)
|
||||
}
|
||||
|
||||
func TestFoldMap(t *testing.T) {
|
||||
src := From("a", "b", "c")
|
||||
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
|
||||
assert.Equal(t, "ABC", fold(src))
|
||||
}
|
||||
|
||||
func ExampleFoldMap() {
|
||||
src := From("a", "b", "c")
|
||||
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
|
||||
fmt.Println(fold(src))
|
||||
|
||||
// Output: ABC
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package generic
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
"github.com/IBM/fp-go/internal/array"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
"github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
@@ -118,6 +119,17 @@ func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B])
|
||||
return filterMap[GA, GB](fa, f)
|
||||
}
|
||||
|
||||
func FilterChain[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[GB]) func(GA) GB {
|
||||
return F.Flow2(
|
||||
FilterMap[GA, []GB](f),
|
||||
Flatten[[]GB],
|
||||
)
|
||||
}
|
||||
|
||||
func Flatten[GAA ~[]GA, GA ~[]A, A any](mma GAA) GA {
|
||||
return MonadChain(mma, F.Identity[GA])
|
||||
}
|
||||
|
||||
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[B]) func(GA) GB {
|
||||
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
||||
}
|
||||
@@ -198,3 +210,19 @@ func Copy[AS ~[]A, A any](b AS) AS {
|
||||
copy(buf, b)
|
||||
return buf
|
||||
}
|
||||
|
||||
func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
return func(f func(A) B) func(AS) B {
|
||||
return func(as AS) B {
|
||||
return array.Reduce(as, func(cur B, a A) B {
|
||||
return m.Concat(cur, f(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,11 +18,17 @@ package generic
|
||||
import (
|
||||
"sort"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/ord"
|
||||
)
|
||||
|
||||
// Sort implements a stable sort on the array given the provided ordering
|
||||
func Sort[GA ~[]T, T any](ord O.Ord[T]) func(ma GA) GA {
|
||||
return SortByKey[GA](ord, F.Identity[T])
|
||||
}
|
||||
|
||||
// SortByKey implements a stable sort on the array given the provided ordering on an extracted key
|
||||
func SortByKey[GA ~[]T, K, T any](ord O.Ord[K], f func(T) K) func(ma GA) GA {
|
||||
|
||||
return func(ma GA) GA {
|
||||
// nothing to sort
|
||||
@@ -34,7 +40,7 @@ func Sort[GA ~[]T, T any](ord O.Ord[T]) func(ma GA) GA {
|
||||
cpy := make(GA, l)
|
||||
copy(cpy, ma)
|
||||
sort.Slice(cpy, func(i, j int) bool {
|
||||
return ord.Compare(cpy[i], cpy[j]) < 0
|
||||
return ord.Compare(f(cpy[i]), f(cpy[j])) < 0
|
||||
})
|
||||
return cpy
|
||||
}
|
||||
|
@@ -24,3 +24,8 @@ import (
|
||||
func Sort[T any](ord O.Ord[T]) func(ma []T) []T {
|
||||
return G.Sort[[]T](ord)
|
||||
}
|
||||
|
||||
// SortByKey implements a stable sort on the array given the provided ordering on an extracted key
|
||||
func SortByKey[K, T any](ord O.Ord[K], f func(T) K) func(ma []T) []T {
|
||||
return G.SortByKey[[]T](ord, f)
|
||||
}
|
||||
|
@@ -388,7 +388,7 @@ func generateApplyHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -266,7 +266,7 @@ func generateBindHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n", pkg)
|
||||
|
||||
|
@@ -150,7 +150,7 @@ func generateEitherHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -27,5 +27,5 @@ func writePackage(f *os.File, pkg string) {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ func generateIdentityHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -81,7 +81,7 @@ func generateIOHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -217,7 +217,7 @@ func generateIOEitherHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -81,7 +81,7 @@ func generateIOOptionHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -148,7 +148,7 @@ func generateOptionHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -337,7 +337,7 @@ func generatePipeHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n", pkg)
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
// 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 cli
|
||||
|
||||
import (
|
||||
@@ -117,7 +118,7 @@ func generateReaderHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -169,7 +169,7 @@ func generateReaderIOEitherHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -355,7 +355,7 @@ func generateTupleHelpers(filename string, count int) error {
|
||||
// some header
|
||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
||||
fmt.Fprintf(f, "// %s\n", time.Now())
|
||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
||||
|
||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
||||
|
||||
|
@@ -1,23 +1,8 @@
|
||||
// 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 readerioeither
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:20.012425 +0200 CEST m=+0.019517901
|
||||
// 2023-08-11 11:37:34.0836986 +0200 CEST m=+0.009764601
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@@ -1,23 +1,8 @@
|
||||
// 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
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:20.012425 +0200 CEST m=+0.019517901
|
||||
// 2023-08-11 11:37:34.0838811 +0200 CEST m=+0.009947101
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
@@ -13,6 +13,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package option defines the [Either] datastructure and its monadic operations
|
||||
package either
|
||||
|
||||
//go:generate go run .. either --count 10 --filename gen.go
|
||||
|
@@ -182,7 +182,7 @@ func FromPredicate[E, A any](pred func(A) bool, onFalse func(A) E) func(A) Eithe
|
||||
}
|
||||
}
|
||||
|
||||
func FromNillable[E, A any](e E) func(*A) Either[E, *A] {
|
||||
func FromNillable[A, E any](e E) func(*A) Either[E, *A] {
|
||||
return FromPredicate(F.IsNonNil[A], F.Constant1[*A](e))
|
||||
}
|
||||
|
||||
|
58
either/examples_create_test.go
Normal file
58
either/examples_create_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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 either
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/IBM/fp-go/errors"
|
||||
)
|
||||
|
||||
func ExampleEither_creation() {
|
||||
// Build an Either
|
||||
leftValue := Left[string](fmt.Errorf("some error"))
|
||||
rightValue := Right[error]("value")
|
||||
|
||||
// Build from a value
|
||||
fromNillable := FromNillable[string](fmt.Errorf("value was nil"))
|
||||
leftFromNil := fromNillable(nil)
|
||||
value := "value"
|
||||
rightFromPointer := fromNillable(&value)
|
||||
|
||||
// some predicate
|
||||
isEven := func(num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
fromEven := FromPredicate(isEven, errors.OnSome[int]("%d is an odd number"))
|
||||
leftFromPred := fromEven(3)
|
||||
rightFromPred := fromEven(4)
|
||||
|
||||
fmt.Println(leftValue)
|
||||
fmt.Println(rightValue)
|
||||
fmt.Println(leftFromNil)
|
||||
fmt.Println(IsRight(rightFromPointer))
|
||||
fmt.Println(leftFromPred)
|
||||
fmt.Println(rightFromPred)
|
||||
|
||||
// Output:
|
||||
// Left[*errors.errorString, string](some error)
|
||||
// Right[<nil>, string](value)
|
||||
// Left[*errors.errorString, *string](value was nil)
|
||||
// true
|
||||
// Left[*errors.errorString, int](3 is an odd number)
|
||||
// Right[<nil>, int](4)
|
||||
|
||||
}
|
64
either/examples_extract_test.go
Normal file
64
either/examples_extract_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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 either
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
N "github.com/IBM/fp-go/number"
|
||||
)
|
||||
|
||||
func ExampleEither_extraction() {
|
||||
leftValue := Left[int](fmt.Errorf("Division by Zero!"))
|
||||
rightValue := Right[error](10)
|
||||
|
||||
// Convert Either[E, A] to A with a default value
|
||||
leftWithDefault := GetOrElse(F.Constant1[error](0))(leftValue) // 0
|
||||
rightWithDefault := GetOrElse(F.Constant1[error](0))(rightValue) // 10
|
||||
|
||||
// Apply a different function on Left(...)/Right(...)
|
||||
doubleOrZero := Fold(F.Constant1[error](0), N.Mul(2)) // func(Either[error, int]) int
|
||||
doubleFromLeft := doubleOrZero(leftValue) // 0
|
||||
doubleFromRight := doubleOrZero(rightValue) // 20
|
||||
|
||||
// Pro-tip: Fold is short for the following:
|
||||
doubleOrZeroBis := F.Flow2(
|
||||
Map[error](N.Mul(2)),
|
||||
GetOrElse(F.Constant1[error](0)),
|
||||
)
|
||||
doubleFromLeftBis := doubleOrZeroBis(leftValue) // 0
|
||||
doubleFromRightBis := doubleOrZeroBis(rightValue) // 20
|
||||
|
||||
fmt.Println(leftValue)
|
||||
fmt.Println(rightValue)
|
||||
fmt.Println(leftWithDefault)
|
||||
fmt.Println(rightWithDefault)
|
||||
fmt.Println(doubleFromLeft)
|
||||
fmt.Println(doubleFromRight)
|
||||
fmt.Println(doubleFromLeftBis)
|
||||
fmt.Println(doubleFromRightBis)
|
||||
|
||||
// Output:
|
||||
// Left[*errors.errorString, int](Division by Zero!)
|
||||
// Right[<nil>, int](10)
|
||||
// 0
|
||||
// 10
|
||||
// 0
|
||||
// 20
|
||||
// 0
|
||||
// 20
|
||||
}
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:23.165015 +0200 CEST m=+0.038998801
|
||||
// 2023-08-11 11:37:35.9608486 +0200 CEST m=+0.009664501
|
||||
|
||||
package either
|
||||
|
||||
import (
|
||||
|
@@ -21,16 +21,12 @@ import (
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
|
||||
func concat[A any](first, second func(A) A) func(A) A {
|
||||
return F.Flow2(first, second)
|
||||
}
|
||||
|
||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Semigroup[A any]() S.Semigroup[func(A) A] {
|
||||
return S.MakeSemigroup(concat[A])
|
||||
return S.MakeSemigroup(F.Flow2[func(A) A, func(A) A])
|
||||
}
|
||||
|
||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
||||
func Monoid[A any]() M.Monoid[func(A) A] {
|
||||
return M.MakeMonoid(concat[A], F.Identity[A])
|
||||
return M.MakeMonoid(F.Flow2[func(A) A, func(A) A], F.Identity[A])
|
||||
}
|
||||
|
@@ -28,6 +28,22 @@ func OnNone(msg string, args ...any) func() error {
|
||||
}
|
||||
}
|
||||
|
||||
// OnSome generates a unary function that produces a formatted error
|
||||
func OnSome[T any](msg string, args ...any) func(T) error {
|
||||
l := len(args)
|
||||
if l == 0 {
|
||||
return func(value T) error {
|
||||
return fmt.Errorf(msg, value)
|
||||
}
|
||||
}
|
||||
return func(value T) error {
|
||||
data := make([]any, l)
|
||||
copy(data[1:], args)
|
||||
data[0] = value
|
||||
return fmt.Errorf(msg, data...)
|
||||
}
|
||||
}
|
||||
|
||||
// OnError generates a unary function that produces a formatted error. The argument
|
||||
// to that function is the root cause of the error and the message will be augmented with
|
||||
// a format string containing %w
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:40.161663 +0200 CEST m=+0.009458101
|
||||
// 2023-08-11 11:37:50.171038 +0200 CEST m=+0.031513801
|
||||
|
||||
package function
|
||||
|
||||
// Combinations for a total of 1 arguments
|
||||
|
@@ -13,6 +13,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package function implements function composition primitives, most prominently [Pipe2] and [Flow2]
|
||||
package function
|
||||
|
||||
//go:generate go run .. pipe --count 20 --filename gen.go
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:27.8029852 +0200 CEST m=+0.051432001
|
||||
// 2023-08-11 11:37:38.4916948 +0200 CEST m=+0.060448601
|
||||
|
||||
package function
|
||||
|
||||
// Pipe0 takes an initial value t0 and successively applies 0 functions where the input of a function is the return value of the previous function
|
||||
|
62
function/pipe_test.go
Normal file
62
function/pipe_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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 function
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func addSthg(value int) int {
|
||||
return value + 1
|
||||
}
|
||||
|
||||
func doSthgElse(value int) int {
|
||||
return value * 2
|
||||
}
|
||||
|
||||
func doFinalSthg(value int) string {
|
||||
return fmt.Sprintf("final value: %d", value)
|
||||
}
|
||||
|
||||
func Example() {
|
||||
// start point
|
||||
value := 1
|
||||
// imperative style
|
||||
value1 := addSthg(value) // 2
|
||||
value2 := doSthgElse(value1) // 4
|
||||
finalValueImperative := doFinalSthg(value2) // "final value: 4"
|
||||
|
||||
// the same but inline
|
||||
finalValueInline := doFinalSthg(doSthgElse(addSthg(value)))
|
||||
|
||||
// with pipe
|
||||
finalValuePipe := Pipe3(value, addSthg, doSthgElse, doFinalSthg)
|
||||
|
||||
// with flow
|
||||
transform := Flow3(addSthg, doSthgElse, doFinalSthg)
|
||||
finalValueFlow := transform(value)
|
||||
|
||||
fmt.Println(finalValueImperative)
|
||||
fmt.Println(finalValueInline)
|
||||
fmt.Println(finalValuePipe)
|
||||
fmt.Println(finalValueFlow)
|
||||
|
||||
// Output:
|
||||
// final value: 4
|
||||
// final value: 4
|
||||
// final value: 4
|
||||
// final value: 4
|
||||
}
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:46.7920356 +0200 CEST m=+0.045177201
|
||||
// 2023-08-11 11:38:00.2678592 +0200 CEST m=+0.008890401
|
||||
|
||||
package identity
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:49.4210571 +0200 CEST m=+0.040316501
|
||||
// 2023-08-11 11:38:01.6948567 +0200 CEST m=+0.013530301
|
||||
|
||||
package apply
|
||||
|
||||
import (
|
||||
|
18
io/gen.go
18
io/gen.go
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:57.7378739 +0200 CEST m=+0.063371401
|
||||
// 2023-08-11 11:38:07.3305497 +0200 CEST m=+0.014821301
|
||||
|
||||
package io
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,6 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:48:57.7499229 +0200 CEST m=+0.075420401
|
||||
// 2023-08-11 11:38:07.3305497 +0200 CEST m=+0.014821301
|
||||
package generic
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:00.7618943 +0200 CEST m=+0.065441701
|
||||
// 2023-08-11 11:38:09.4187123 +0200 CEST m=+0.099620101
|
||||
|
||||
package ioeither
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,6 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:00.7765028 +0200 CEST m=+0.080050201
|
||||
// 2023-08-11 11:38:09.4489926 +0200 CEST m=+0.129900401
|
||||
package generic
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:03.8471425 +0200 CEST m=+0.087124201
|
||||
// 2023-08-11 11:38:12.1021634 +0200 CEST m=+0.041956701
|
||||
|
||||
package iooption
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,6 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:03.8541587 +0200 CEST m=+0.094140401
|
||||
// 2023-08-11 11:38:12.1210201 +0200 CEST m=+0.060813401
|
||||
package generic
|
||||
|
||||
import (
|
||||
|
26
iterator/stateless/first.go
Normal file
26
iterator/stateless/first.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// 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 stateless
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// First returns the first item in an iterator if such an item exists
|
||||
func First[U any](mu Iterator[U]) O.Option[U] {
|
||||
return G.First[Iterator[U]](mu)
|
||||
}
|
41
iterator/stateless/first_test.go
Normal file
41
iterator/stateless/first_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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 stateless
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
O "github.com/IBM/fp-go/option"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFirst(t *testing.T) {
|
||||
|
||||
seq := From(1, 2, 3)
|
||||
|
||||
fst := First(seq)
|
||||
|
||||
assert.Equal(t, O.Of(1), fst)
|
||||
}
|
||||
|
||||
func TestNoFirst(t *testing.T) {
|
||||
|
||||
seq := Empty[int]()
|
||||
|
||||
fst := First(seq)
|
||||
|
||||
assert.Equal(t, O.None[int](), fst)
|
||||
}
|
30
iterator/stateless/generic/first.go
Normal file
30
iterator/stateless/generic/first.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 generic
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
// First returns the first item in an iterator if such an item exists
|
||||
func First[GU ~func() O.Option[T.Tuple2[GU, U]], U any](mu GU) O.Option[U] {
|
||||
return F.Pipe1(
|
||||
mu(),
|
||||
O.Map(T.Second[GU, U]),
|
||||
)
|
||||
}
|
@@ -20,6 +20,7 @@ import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
"github.com/IBM/fp-go/internal/utils"
|
||||
IO "github.com/IBM/fp-go/iooption/generic"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
N "github.com/IBM/fp-go/number"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
@@ -49,18 +50,21 @@ func FromArray[GU ~func() O.Option[T.Tuple2[GU, U]], US ~[]U, U any](as US) GU {
|
||||
})(as)
|
||||
}
|
||||
|
||||
// reduce applies a function for each value of the iterator with a floating result
|
||||
func reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](as GU, f func(V, U) V, initial V) V {
|
||||
next, ok := O.Unwrap(as())
|
||||
current := initial
|
||||
for ok {
|
||||
// next (with bad side effect)
|
||||
current = f(current, next.F2)
|
||||
next, ok = O.Unwrap(next.F1())
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
// Reduce applies a function for each value of the iterator with a floating result
|
||||
func Reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](f func(V, U) V, initial V) func(GU) V {
|
||||
return func(as GU) V {
|
||||
next, ok := O.Unwrap(as())
|
||||
current := initial
|
||||
for ok {
|
||||
// next (with bad side effect)
|
||||
current = f(current, next.F2)
|
||||
next, ok = O.Unwrap(next.F1())
|
||||
}
|
||||
return current
|
||||
}
|
||||
return F.Bind23of3(reduce[GU, U, V])(f, initial)
|
||||
}
|
||||
|
||||
// ToArray converts the iterator to an array
|
||||
@@ -216,3 +220,22 @@ func Ap[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tu
|
||||
func MonadAp[GUV ~func() O.Option[T.Tuple2[GUV, func(U) V]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](fab GUV, ma GU) GV {
|
||||
return Ap[GUV, GV, GU](ma)(fab)
|
||||
}
|
||||
|
||||
func FilterChain[GVV ~func() O.Option[T.Tuple2[GVV, GV]], GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) O.Option[GV], U, V any](f FCT) func(ma GU) GV {
|
||||
return F.Flow2(
|
||||
FilterMap[GVV, GU](f),
|
||||
Flatten[GVV],
|
||||
)
|
||||
}
|
||||
|
||||
func FoldMap[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) V, U, V any](m M.Monoid[V]) func(FCT) func(ma GU) V {
|
||||
return func(f FCT) func(ma GU) V {
|
||||
return Reduce[GU](func(cur V, a U) V {
|
||||
return m.Concat(cur, f(a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
|
||||
func Fold[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m M.Monoid[U]) func(ma GU) U {
|
||||
return Reduce[GU](m.Concat, m.Empty())
|
||||
}
|
||||
|
27
iterator/stateless/generic/last.go
Normal file
27
iterator/stateless/generic/last.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// 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
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
// Last returns the last item in an iterator if such an item exists
|
||||
func Last[GU ~func() O.Option[T.Tuple2[GU, U]], U any](mu GU) O.Option[U] {
|
||||
return reduce(mu, F.Ignore1of2[O.Option[U]](O.Of[U]), O.None[U]())
|
||||
}
|
@@ -18,6 +18,7 @@ package stateless
|
||||
import (
|
||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||
L "github.com/IBM/fp-go/lazy"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
@@ -118,3 +119,18 @@ func Repeat[U any](n int, a U) Iterator[U] {
|
||||
func Count(start int) Iterator[int] {
|
||||
return G.Count[Iterator[int]](start)
|
||||
}
|
||||
|
||||
// FilterChain filters and transforms the content of an iterator
|
||||
func FilterChain[U, V any](f func(U) O.Option[Iterator[V]]) func(ma Iterator[U]) Iterator[V] {
|
||||
return G.FilterChain[Iterator[Iterator[V]], Iterator[V], Iterator[U]](f)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds an iterator. Map the iterator passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMap[U, V any](m M.Monoid[V]) func(func(U) V) func(ma Iterator[U]) V {
|
||||
return G.FoldMap[Iterator[U], func(U) V, U, V](m)
|
||||
}
|
||||
|
||||
// Fold folds the iterator using the provided Monoid.
|
||||
func Fold[U any](m M.Monoid[U]) func(Iterator[U]) U {
|
||||
return G.Fold[Iterator[U]](m)
|
||||
}
|
||||
|
@@ -18,12 +18,14 @@ package stateless
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
"github.com/IBM/fp-go/internal/utils"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
S "github.com/IBM/fp-go/string"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -102,3 +104,14 @@ func TestAp(t *testing.T) {
|
||||
|
||||
assert.Equal(t, A.From("a-1-c", "a-1-d", "a-2-c", "a-2-d", "b-1-c", "b-1-d", "b-2-c", "b-2-d"), it)
|
||||
}
|
||||
|
||||
func ExampleFoldMap() {
|
||||
src := From("a", "b", "c")
|
||||
|
||||
fold := FoldMap[string](S.Monoid)(strings.ToUpper)
|
||||
|
||||
fmt.Println(fold(src))
|
||||
|
||||
// Output: ABC
|
||||
|
||||
}
|
||||
|
27
iterator/stateless/last.go
Normal file
27
iterator/stateless/last.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// 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 stateless
|
||||
|
||||
import (
|
||||
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
)
|
||||
|
||||
// Last returns the last item in an iterator if such an item exists
|
||||
// Note that the function will consume the [Iterator] in this call completely, to identify the last element. Do not use this for infinite iterators
|
||||
func Last[U any](mu Iterator[U]) O.Option[U] {
|
||||
return G.Last[Iterator[U]](mu)
|
||||
}
|
41
iterator/stateless/last_test.go
Normal file
41
iterator/stateless/last_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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 stateless
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
O "github.com/IBM/fp-go/option"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLast(t *testing.T) {
|
||||
|
||||
seq := From(1, 2, 3)
|
||||
|
||||
fst := Last(seq)
|
||||
|
||||
assert.Equal(t, O.Of(3), fst)
|
||||
}
|
||||
|
||||
func TestNoLast(t *testing.T) {
|
||||
|
||||
seq := Empty[int]()
|
||||
|
||||
fst := Last(seq)
|
||||
|
||||
assert.Equal(t, O.None[int](), fst)
|
||||
}
|
@@ -30,6 +30,13 @@ func Add[T Number](left T) func(T) T {
|
||||
}
|
||||
}
|
||||
|
||||
// Mul is a curried function used to add two numbers
|
||||
func Mul[T Number](coeff T) func(T) T {
|
||||
return func(value T) T {
|
||||
return coeff * value
|
||||
}
|
||||
}
|
||||
|
||||
// Inc is a function that increments a number
|
||||
func Inc[T Number](value T) T {
|
||||
return value + 1
|
||||
|
@@ -13,6 +13,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package option defines the [Option] datastructure and its monadic operations
|
||||
package option
|
||||
|
||||
//go:generate go run .. option --count 10 --filename gen.go
|
||||
|
55
option/examples_create_test.go
Normal file
55
option/examples_create_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// 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 option
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ExampleOption_creation() {
|
||||
|
||||
// Build an Option
|
||||
none1 := None[int]()
|
||||
some1 := Some("value")
|
||||
|
||||
// Build from a value
|
||||
fromNillable := FromNillable[string]
|
||||
nonFromNil := fromNillable(nil) // None[*string]
|
||||
value := "value"
|
||||
someFromPointer := fromNillable(&value) // Some[*string](xxx)
|
||||
|
||||
// some predicate
|
||||
isEven := func(num int) bool {
|
||||
return num%2 == 0
|
||||
}
|
||||
|
||||
fromEven := FromPredicate(isEven)
|
||||
noneFromPred := fromEven(3) // None[int]
|
||||
someFromPred := fromEven(4) // Some[int](4)
|
||||
|
||||
fmt.Println(none1)
|
||||
fmt.Println(some1)
|
||||
fmt.Println(nonFromNil)
|
||||
fmt.Println(IsSome(someFromPointer))
|
||||
fmt.Println(noneFromPred)
|
||||
fmt.Println(someFromPred)
|
||||
|
||||
// Output:
|
||||
// None[int]
|
||||
// Some[string](value)
|
||||
// None[*string]
|
||||
// true
|
||||
// None[int]
|
||||
// Some[int](4)
|
||||
}
|
73
option/examples_extract_test.go
Normal file
73
option/examples_extract_test.go
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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 option
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
N "github.com/IBM/fp-go/number"
|
||||
)
|
||||
|
||||
func ExampleOption_extraction() {
|
||||
|
||||
noneValue := None[int]()
|
||||
someValue := Of(42)
|
||||
|
||||
// Convert Option[T] to T
|
||||
fromNone, okFromNone := Unwrap(noneValue) // 0, false
|
||||
fromSome, okFromSome := Unwrap(someValue) // 42, true
|
||||
|
||||
// Convert Option[T] with a default value
|
||||
noneWithDefault := GetOrElse(F.Constant(0))(noneValue) // 0
|
||||
someWithDefault := GetOrElse(F.Constant(0))(someValue) // 42
|
||||
|
||||
// Apply a different function on None/Some(...)
|
||||
doubleOrZero := Fold(
|
||||
F.Constant(0), // none case
|
||||
N.Mul(2), // some case
|
||||
) // func(ma Option[int]) int
|
||||
|
||||
doubleFromNone := doubleOrZero(noneValue) // 0
|
||||
doubleFromSome := doubleOrZero(someValue) // 84
|
||||
|
||||
// Pro-tip: Fold is short for the following:
|
||||
doubleOfZeroBis := F.Flow2(
|
||||
Map(N.Mul(2)), // some case
|
||||
GetOrElse(F.Constant(0)), // none case
|
||||
)
|
||||
doubleFromNoneBis := doubleOfZeroBis(noneValue) // 0
|
||||
doubleFromSomeBis := doubleOfZeroBis(someValue) // 84
|
||||
|
||||
fmt.Printf("%d, %t\n", fromNone, okFromNone)
|
||||
fmt.Printf("%d, %t\n", fromSome, okFromSome)
|
||||
fmt.Println(noneWithDefault)
|
||||
fmt.Println(someWithDefault)
|
||||
fmt.Println(doubleFromNone)
|
||||
fmt.Println(doubleFromSome)
|
||||
fmt.Println(doubleFromNoneBis)
|
||||
fmt.Println(doubleFromSomeBis)
|
||||
|
||||
// Output:
|
||||
// 0, false
|
||||
// 42, true
|
||||
// 0
|
||||
// 42
|
||||
// 0
|
||||
// 84
|
||||
// 0
|
||||
// 84
|
||||
}
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:06.6236747 +0200 CEST m=+0.039283301
|
||||
// 2023-08-11 11:38:14.9503867 +0200 CEST m=+0.020206701
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:14.4173227 +0200 CEST m=+0.013163201
|
||||
// 2023-08-11 11:38:23.1396887 +0200 CEST m=+0.020805301
|
||||
|
||||
package reader
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,6 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:14.4173227 +0200 CEST m=+0.013163201
|
||||
// 2023-08-11 11:38:23.1402159 +0200 CEST m=+0.021332501
|
||||
package generic
|
||||
|
||||
// From0 converts a function with 1 parameters returning a [R] into a function with 0 parameters returning a [GRA]
|
||||
|
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:16.5272334 +0200 CEST m=+0.043108701
|
||||
// 2023-08-11 11:38:26.9546728 +0200 CEST m=+0.032178301
|
||||
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
|
@@ -1,21 +1,6 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:16.5292332 +0200 CEST m=+0.045108501
|
||||
// 2023-08-11 11:38:26.9556725 +0200 CEST m=+0.033178001
|
||||
package generic
|
||||
|
||||
import (
|
||||
|
17
record/doc.go
Normal file
17
record/doc.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// 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 record contains monadic operations for maps as well as a rich set of utility functions
|
||||
package record
|
@@ -16,6 +16,7 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
F "github.com/IBM/fp-go/function"
|
||||
M "github.com/IBM/fp-go/monoid"
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
@@ -26,3 +27,17 @@ func UnionMonoid[N ~map[K]V, K comparable, V any](s S.Semigroup[V]) M.Monoid[N]
|
||||
Empty[N](),
|
||||
)
|
||||
}
|
||||
|
||||
func UnionLastMonoid[N ~map[K]V, K comparable, V any]() M.Monoid[N] {
|
||||
return M.MakeMonoid(
|
||||
unionLast[N],
|
||||
Empty[N](),
|
||||
)
|
||||
}
|
||||
|
||||
func UnionFirstMonoid[N ~map[K]V, K comparable, V any]() M.Monoid[N] {
|
||||
return M.MakeMonoid(
|
||||
F.Swap(unionLast[N]),
|
||||
Empty[N](),
|
||||
)
|
||||
}
|
||||
|
@@ -16,10 +16,14 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
F "github.com/IBM/fp-go/function"
|
||||
G "github.com/IBM/fp-go/internal/record"
|
||||
Mg "github.com/IBM/fp-go/magma"
|
||||
Mo "github.com/IBM/fp-go/monoid"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
"github.com/IBM/fp-go/ord"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
@@ -39,6 +43,46 @@ func Values[M ~map[K]V, GV ~[]V, K comparable, V any](r M) GV {
|
||||
return collect[M, GV](r, F.Second[K, V])
|
||||
}
|
||||
|
||||
func KeysOrd[M ~map[K]V, GK ~[]K, K comparable, V any](o ord.Ord[K]) func(r M) GK {
|
||||
return func(r M) GK {
|
||||
return collectOrd[M, GK](o, r, F.First[K, V])
|
||||
}
|
||||
}
|
||||
|
||||
func ValuesOrd[M ~map[K]V, GV ~[]V, K comparable, V any](o ord.Ord[K]) func(r M) GV {
|
||||
return func(r M) GV {
|
||||
return collectOrd[M, GV](o, r, F.Second[K, V])
|
||||
}
|
||||
}
|
||||
|
||||
func collectOrd[M ~map[K]V, GR ~[]R, K comparable, V, R any](o ord.Ord[K], r M, f func(K, V) R) GR {
|
||||
// create the entries
|
||||
entries := toEntriesOrd[M, []T.Tuple2[K, V]](o, r)
|
||||
// collect this array
|
||||
ft := T.Tupled2(f)
|
||||
count := len(entries)
|
||||
result := make(GR, count)
|
||||
for i := count - 1; i >= 0; i-- {
|
||||
result[i] = ft(entries[i])
|
||||
}
|
||||
// done
|
||||
return result
|
||||
}
|
||||
|
||||
func reduceOrd[M ~map[K]V, K comparable, V, R any](o ord.Ord[K], r M, f func(K, R, V) R, initial R) R {
|
||||
// create the entries
|
||||
entries := toEntriesOrd[M, []T.Tuple2[K, V]](o, r)
|
||||
// collect this array
|
||||
current := initial
|
||||
count := len(entries)
|
||||
for i := 0; i < count; i++ {
|
||||
t := entries[i]
|
||||
current = f(T.First(t), current, T.Second(t))
|
||||
}
|
||||
// done
|
||||
return current
|
||||
}
|
||||
|
||||
func collect[M ~map[K]V, GR ~[]R, K comparable, V, R any](r M, f func(K, V) R) GR {
|
||||
count := len(r)
|
||||
result := make(GR, count)
|
||||
@@ -82,6 +126,34 @@ func MonadMap[M ~map[K]V, N ~map[K]R, K comparable, V, R any](r M, f func(V) R)
|
||||
return MonadMapWithIndex[M, N](r, F.Ignore1of2[K](f))
|
||||
}
|
||||
|
||||
func MonadChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N], r M, f func(K, V1) N) N {
|
||||
return G.ReduceWithIndex(r, func(k K, dst N, b V1) N {
|
||||
return m.Concat(dst, f(k, b))
|
||||
}, m.Empty())
|
||||
}
|
||||
|
||||
func MonadChain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N], r M, f func(V1) N) N {
|
||||
return G.Reduce(r, func(dst N, b V1) N {
|
||||
return m.Concat(dst, f(b))
|
||||
}, m.Empty())
|
||||
}
|
||||
|
||||
func ChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(K, V1) N) func(M) N {
|
||||
return func(f func(K, V1) N) func(M) N {
|
||||
return func(ma M) N {
|
||||
return MonadChainWithIndex(m, ma, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Chain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(V1) N) func(M) N {
|
||||
return func(f func(V1) N) func(M) N {
|
||||
return func(ma M) N {
|
||||
return MonadChain(m, ma, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func MonadMapWithIndex[M ~map[K]V, N ~map[K]R, K comparable, V, R any](r M, f func(K, V) R) N {
|
||||
return G.ReduceWithIndex(r, func(k K, dst N, v V) N {
|
||||
return upsertAtReadWrite(dst, k, f(k, v))
|
||||
@@ -114,15 +186,14 @@ func MapRefWithIndex[M ~map[K]V, N ~map[K]R, K comparable, V, R any](f func(K, *
|
||||
return F.Bind2nd(MonadMapRefWithIndex[M, N, K, V, R], f)
|
||||
}
|
||||
|
||||
func lookup[M ~map[K]V, K comparable, V any](r M, k K) O.Option[V] {
|
||||
if val, ok := r[k]; ok {
|
||||
return O.Some(val)
|
||||
}
|
||||
return O.None[V]()
|
||||
}
|
||||
|
||||
func Lookup[M ~map[K]V, K comparable, V any](k K) func(M) O.Option[V] {
|
||||
return F.Bind2nd(lookup[M, K, V], k)
|
||||
n := O.None[V]()
|
||||
return func(m M) O.Option[V] {
|
||||
if val, ok := m[k]; ok {
|
||||
return O.Some(val)
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
func Has[M ~map[K]V, K comparable, V any](k K, r M) bool {
|
||||
@@ -161,6 +232,31 @@ func union[M ~map[K]V, K comparable, V any](m Mg.Magma[V], left M, right M) M {
|
||||
return result
|
||||
}
|
||||
|
||||
func unionLast[M ~map[K]V, K comparable, V any](left M, right M) M {
|
||||
lenLeft := len(left)
|
||||
|
||||
if lenLeft == 0 {
|
||||
return right
|
||||
}
|
||||
|
||||
lenRight := len(right)
|
||||
if lenRight == 0 {
|
||||
return left
|
||||
}
|
||||
|
||||
result := make(M, lenLeft+lenRight)
|
||||
|
||||
for k, v := range left {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
for k, v := range right {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func Union[M ~map[K]V, K comparable, V any](m Mg.Magma[V]) func(M) func(M) M {
|
||||
return func(right M) func(M) M {
|
||||
return func(left M) M {
|
||||
@@ -169,6 +265,22 @@ func Union[M ~map[K]V, K comparable, V any](m Mg.Magma[V]) func(M) func(M) M {
|
||||
}
|
||||
}
|
||||
|
||||
func UnionLast[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||
return func(left M) M {
|
||||
return unionLast(left, right)
|
||||
}
|
||||
}
|
||||
|
||||
func Merge[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||
return UnionLast(right)
|
||||
}
|
||||
|
||||
func UnionFirst[M ~map[K]V, K comparable, V any](right M) func(M) M {
|
||||
return func(left M) M {
|
||||
return unionLast(right, left)
|
||||
}
|
||||
}
|
||||
|
||||
func Empty[M ~map[K]V, K comparable, V any]() M {
|
||||
return make(M)
|
||||
}
|
||||
@@ -181,6 +293,27 @@ func ToArray[M ~map[K]V, GT ~[]T.Tuple2[K, V], K comparable, V any](r M) GT {
|
||||
return collect[M, GT](r, T.MakeTuple2[K, V])
|
||||
}
|
||||
|
||||
func toEntriesOrd[M ~map[K]V, GT ~[]T.Tuple2[K, V], K comparable, V any](o ord.Ord[K], r M) GT {
|
||||
// total number of elements
|
||||
count := len(r)
|
||||
// produce an array that we can sort by key
|
||||
entries := make(GT, count)
|
||||
idx := 0
|
||||
for k, v := range r {
|
||||
entries[idx] = T.MakeTuple2(k, v)
|
||||
idx++
|
||||
}
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
return o.Compare(T.First(entries[i]), T.First(entries[j])) < 0
|
||||
})
|
||||
// final entries
|
||||
return entries
|
||||
}
|
||||
|
||||
func ToEntriesOrd[M ~map[K]V, GT ~[]T.Tuple2[K, V], K comparable, V any](o ord.Ord[K]) func(r M) GT {
|
||||
return F.Bind1st(toEntriesOrd[M, GT, K, V], o)
|
||||
}
|
||||
|
||||
func ToEntries[M ~map[K]V, GT ~[]T.Tuple2[K, V], K comparable, V any](r M) GT {
|
||||
return ToArray[M, GT](r)
|
||||
}
|
||||
@@ -269,6 +402,33 @@ func FilterMap[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](f func(V1) O.
|
||||
return F.Bind2nd(filterMapWithIndex[M, N, K, V1, V2], F.Ignore1of2[K](f))
|
||||
}
|
||||
|
||||
// Flatten converts a nested map into a regular map
|
||||
func Flatten[M ~map[K]N, N ~map[K]V, K comparable, V any](m Mo.Monoid[N]) func(M) N {
|
||||
return Chain[M, N](m)(F.Identity[N])
|
||||
}
|
||||
|
||||
// FilterChainWithIndex creates a new map with only the elements for which the transformation function creates a Some
|
||||
func FilterChainWithIndex[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(K, V1) O.Option[N]) func(M) N {
|
||||
flatten := Flatten[map[K]N, N](m)
|
||||
return func(f func(K, V1) O.Option[N]) func(M) N {
|
||||
return F.Flow2(
|
||||
FilterMapWithIndex[M, map[K]N](f),
|
||||
flatten,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// FilterChain creates a new map with only the elements for which the transformation function creates a Some
|
||||
func FilterChain[M ~map[K]V1, N ~map[K]V2, K comparable, V1, V2 any](m Mo.Monoid[N]) func(func(V1) O.Option[N]) func(M) N {
|
||||
flatten := Flatten[map[K]N, N](m)
|
||||
return func(f func(V1) O.Option[N]) func(M) N {
|
||||
return F.Flow2(
|
||||
FilterMap[M, map[K]N](f),
|
||||
flatten,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// IsNil checks if the map is set to nil
|
||||
func IsNil[M ~map[K]V, K comparable, V any](m M) bool {
|
||||
return m == nil
|
||||
@@ -283,3 +443,67 @@ func IsNonNil[M ~map[K]V, K comparable, V any](m M) bool {
|
||||
func ConstNil[M ~map[K]V, K comparable, V any]() M {
|
||||
return (M)(nil)
|
||||
}
|
||||
|
||||
func FoldMap[AS ~map[K]A, K comparable, A, B any](m Mo.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
return func(f func(A) B) func(AS) B {
|
||||
return Reduce[AS](func(cur B, a A) B {
|
||||
return m.Concat(cur, f(a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
|
||||
func Fold[AS ~map[K]A, K comparable, A any](m Mo.Monoid[A]) func(AS) A {
|
||||
return Reduce[AS](m.Concat, m.Empty())
|
||||
}
|
||||
|
||||
func FoldMapWithIndex[AS ~map[K]A, K comparable, A, B any](m Mo.Monoid[B]) func(func(K, A) B) func(AS) B {
|
||||
return func(f func(K, A) B) func(AS) B {
|
||||
return ReduceWithIndex[AS](func(k K, cur B, a A) B {
|
||||
return m.Concat(cur, f(k, a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
|
||||
func ReduceOrdWithIndex[M ~map[K]V, K comparable, V, R any](o ord.Ord[K]) func(func(K, R, V) R, R) func(M) R {
|
||||
return func(f func(K, R, V) R, initial R) func(M) R {
|
||||
return func(m M) R {
|
||||
return reduceOrd(o, m, f, initial)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ReduceOrd[M ~map[K]V, K comparable, V, R any](o ord.Ord[K]) func(func(R, V) R, R) func(M) R {
|
||||
ro := ReduceOrdWithIndex[M, K, V, R](o)
|
||||
return func(f func(R, V) R, initial R) func(M) R {
|
||||
return ro(F.Ignore1of3[K](f), initial)
|
||||
}
|
||||
}
|
||||
|
||||
func FoldMapOrd[AS ~map[K]A, K comparable, A, B any](o ord.Ord[K]) func(m Mo.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
red := ReduceOrd[AS, K, A, B](o)
|
||||
return func(m Mo.Monoid[B]) func(func(A) B) func(AS) B {
|
||||
return func(f func(A) B) func(AS) B {
|
||||
return red(func(cur B, a A) B {
|
||||
return m.Concat(cur, f(a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func FoldOrd[AS ~map[K]A, K comparable, A any](o ord.Ord[K]) func(m Mo.Monoid[A]) func(AS) A {
|
||||
red := ReduceOrd[AS, K, A, A](o)
|
||||
return func(m Mo.Monoid[A]) func(AS) A {
|
||||
return red(m.Concat, m.Empty())
|
||||
}
|
||||
}
|
||||
|
||||
func FoldMapOrdWithIndex[AS ~map[K]A, K comparable, A, B any](o ord.Ord[K]) func(m Mo.Monoid[B]) func(func(K, A) B) func(AS) B {
|
||||
red := ReduceOrdWithIndex[AS, K, A, B](o)
|
||||
return func(m Mo.Monoid[B]) func(func(K, A) B) func(AS) B {
|
||||
return func(f func(K, A) B) func(AS) B {
|
||||
return red(func(k K, cur B, a A) B {
|
||||
return m.Concat(cur, f(k, a))
|
||||
}, m.Empty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,8 +20,19 @@ import (
|
||||
)
|
||||
|
||||
func UnionSemigroup[N ~map[K]V, K comparable, V any](s S.Semigroup[V]) S.Semigroup[N] {
|
||||
union := Union[N, K, V](s)
|
||||
return S.MakeSemigroup(func(first N, second N) N {
|
||||
return union(second)(first)
|
||||
return union[N, K, V](S.ToMagma(s), first, second)
|
||||
})
|
||||
}
|
||||
|
||||
func UnionLastSemigroup[N ~map[K]V, K comparable, V any]() S.Semigroup[N] {
|
||||
return S.MakeSemigroup(func(first N, second N) N {
|
||||
return unionLast[N, K, V](first, second)
|
||||
})
|
||||
}
|
||||
|
||||
func UnionFirstSemigroup[N ~map[K]V, K comparable, V any]() S.Semigroup[N] {
|
||||
return S.MakeSemigroup(func(first N, second N) N {
|
||||
return unionLast[N, K, V](second, first)
|
||||
})
|
||||
}
|
||||
|
@@ -21,6 +21,22 @@ import (
|
||||
S "github.com/IBM/fp-go/semigroup"
|
||||
)
|
||||
|
||||
// UnionMonoid computes the union of two maps of the same type
|
||||
func UnionMonoid[K comparable, V any](s S.Semigroup[V]) M.Monoid[map[K]V] {
|
||||
return G.UnionMonoid[map[K]V](s)
|
||||
}
|
||||
|
||||
// UnionLastMonoid computes the union of two maps of the same type giving the last map precedence
|
||||
func UnionLastMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||
return G.UnionLastMonoid[map[K]V]()
|
||||
}
|
||||
|
||||
// UnionFirstMonoid computes the union of two maps of the same type giving the first map precedence
|
||||
func UnionFirstMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||
return G.UnionFirstMonoid[map[K]V]()
|
||||
}
|
||||
|
||||
// MergeMonoid computes the union of two maps of the same type giving the last map precedence
|
||||
func MergeMonoid[K comparable, V any]() M.Monoid[map[K]V] {
|
||||
return G.UnionLastMonoid[map[K]V]()
|
||||
}
|
||||
|
@@ -17,27 +17,34 @@ package record
|
||||
|
||||
import (
|
||||
Mg "github.com/IBM/fp-go/magma"
|
||||
Mo "github.com/IBM/fp-go/monoid"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
"github.com/IBM/fp-go/ord"
|
||||
G "github.com/IBM/fp-go/record/generic"
|
||||
T "github.com/IBM/fp-go/tuple"
|
||||
)
|
||||
|
||||
// IsEmpty tests if a map is empty
|
||||
func IsEmpty[K comparable, V any](r map[K]V) bool {
|
||||
return G.IsEmpty(r)
|
||||
}
|
||||
|
||||
// IsNonEmpty tests if a map is not empty
|
||||
func IsNonEmpty[K comparable, V any](r map[K]V) bool {
|
||||
return G.IsNonEmpty(r)
|
||||
}
|
||||
|
||||
// Keys returns the key in a map
|
||||
func Keys[K comparable, V any](r map[K]V) []K {
|
||||
return G.Keys[map[K]V, []K](r)
|
||||
}
|
||||
|
||||
// Values returns the values in a map
|
||||
func Values[K comparable, V any](r map[K]V) []V {
|
||||
return G.Values[map[K]V, []V](r)
|
||||
}
|
||||
|
||||
// Collect applies a collector function to the key value pairs in a map and returns the result as an array
|
||||
func Collect[K comparable, V, R any](f func(K, V) R) func(map[K]V) []R {
|
||||
return G.Collect[map[K]V, []R](f)
|
||||
}
|
||||
@@ -90,10 +97,12 @@ func MapRefWithIndex[K comparable, V, R any](f func(K, *V) R) func(map[K]V) map[
|
||||
return G.MapRefWithIndex[map[K]V, map[K]R](f)
|
||||
}
|
||||
|
||||
// Lookup returns the entry for a key in a map if it exists
|
||||
func Lookup[K comparable, V any](k K) func(map[K]V) O.Option[V] {
|
||||
return G.Lookup[map[K]V](k)
|
||||
}
|
||||
|
||||
// Has tests if a key is contained in a map
|
||||
func Has[K comparable, V any](k K, r map[K]V) bool {
|
||||
return G.Has(k, r)
|
||||
}
|
||||
@@ -102,10 +111,17 @@ func Union[K comparable, V any](m Mg.Magma[V]) func(map[K]V) func(map[K]V) map[K
|
||||
return G.Union[map[K]V](m)
|
||||
}
|
||||
|
||||
// Merge combines two maps giving the values in the right one precedence. Also refer to [MergeMonoid]
|
||||
func Merge[K comparable, V any](right map[K]V) func(map[K]V) map[K]V {
|
||||
return G.Merge[map[K]V](right)
|
||||
}
|
||||
|
||||
// Empty creates an empty map
|
||||
func Empty[K comparable, V any]() map[K]V {
|
||||
return G.Empty[map[K]V]()
|
||||
}
|
||||
|
||||
// Size returns the number of elements in a map
|
||||
func Size[K comparable, V any](r map[K]V) int {
|
||||
return G.Size(r)
|
||||
}
|
||||
@@ -130,6 +146,7 @@ func DeleteAt[K comparable, V any](k K) func(map[K]V) map[K]V {
|
||||
return G.DeleteAt[map[K]V](k)
|
||||
}
|
||||
|
||||
// Singleton creates a new map with a single entry
|
||||
func Singleton[K comparable, V any](k K, v V) map[K]V {
|
||||
return G.Singleton[map[K]V](k, v)
|
||||
}
|
||||
@@ -168,3 +185,84 @@ func IsNonNil[K comparable, V any](m map[K]V) bool {
|
||||
func ConstNil[K comparable, V any]() map[K]V {
|
||||
return (map[K]V)(nil)
|
||||
}
|
||||
|
||||
func MonadChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2], r map[K]V1, f func(K, V1) map[K]V2) map[K]V2 {
|
||||
return G.MonadChainWithIndex(m, r, f)
|
||||
}
|
||||
|
||||
func MonadChain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2], r map[K]V1, f func(V1) map[K]V2) map[K]V2 {
|
||||
return G.MonadChain(m, r, f)
|
||||
}
|
||||
|
||||
func ChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(K, V1) map[K]V2) func(map[K]V1) map[K]V2 {
|
||||
return G.ChainWithIndex[map[K]V1](m)
|
||||
}
|
||||
|
||||
func Chain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(V1) map[K]V2) func(map[K]V1) map[K]V2 {
|
||||
return G.Chain[map[K]V1](m)
|
||||
}
|
||||
|
||||
// Flatten converts a nested map into a regular map
|
||||
func Flatten[K comparable, V any](m Mo.Monoid[map[K]V]) func(map[K]map[K]V) map[K]V {
|
||||
return G.Flatten[map[K]map[K]V](m)
|
||||
}
|
||||
|
||||
// FilterChainWithIndex creates a new map with only the elements for which the transformation function creates a Some
|
||||
func FilterChainWithIndex[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(K, V1) O.Option[map[K]V2]) func(map[K]V1) map[K]V2 {
|
||||
return G.FilterChainWithIndex[map[K]V1](m)
|
||||
}
|
||||
|
||||
// FilterChain creates a new map with only the elements for which the transformation function creates a Some
|
||||
func FilterChain[V1 any, K comparable, V2 any](m Mo.Monoid[map[K]V2]) func(func(V1) O.Option[map[K]V2]) func(map[K]V1) map[K]V2 {
|
||||
return G.FilterChain[map[K]V1](m)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds a record. Map the record passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMap[K comparable, A, B any](m Mo.Monoid[B]) func(func(A) B) func(map[K]A) B {
|
||||
return G.FoldMap[map[K]A](m)
|
||||
}
|
||||
|
||||
// FoldMapWithIndex maps and folds a record. Map the record passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||
func FoldMapWithIndex[K comparable, A, B any](m Mo.Monoid[B]) func(func(K, A) B) func(map[K]A) B {
|
||||
return G.FoldMapWithIndex[map[K]A](m)
|
||||
}
|
||||
|
||||
// Fold folds the record using the provided Monoid.
|
||||
func Fold[K comparable, A any](m Mo.Monoid[A]) func(map[K]A) A {
|
||||
return G.Fold[map[K]A](m)
|
||||
}
|
||||
|
||||
// ReduceOrdWithIndex reduces a map into a single value via a reducer function making sure that the keys are passed to the reducer in the specified order
|
||||
func ReduceOrdWithIndex[V, R any, K comparable](o ord.Ord[K]) func(func(K, R, V) R, R) func(map[K]V) R {
|
||||
return G.ReduceOrdWithIndex[map[K]V, K, V, R](o)
|
||||
}
|
||||
|
||||
// ReduceOrd reduces a map into a single value via a reducer function making sure that the keys are passed to the reducer in the specified order
|
||||
func ReduceOrd[V, R any, K comparable](o ord.Ord[K]) func(func(R, V) R, R) func(map[K]V) R {
|
||||
return G.ReduceOrd[map[K]V, K, V, R](o)
|
||||
}
|
||||
|
||||
// FoldMap maps and folds a record. Map the record passing each value to the iterating function. Then fold the results using the provided Monoid and the items in the provided order
|
||||
func FoldMapOrd[A, B any, K comparable](o ord.Ord[K]) func(m Mo.Monoid[B]) func(func(A) B) func(map[K]A) B {
|
||||
return G.FoldMapOrd[map[K]A, K, A, B](o)
|
||||
}
|
||||
|
||||
// Fold folds the record using the provided Monoid with the items passed in the given order
|
||||
func FoldOrd[A any, K comparable](o ord.Ord[K]) func(m Mo.Monoid[A]) func(map[K]A) A {
|
||||
return G.FoldOrd[map[K]A, K, A](o)
|
||||
}
|
||||
|
||||
// FoldMapWithIndex maps and folds a record. Map the record passing each value to the iterating function. Then fold the results using the provided Monoid and the items in the provided order
|
||||
func FoldMapOrdWithIndex[K comparable, A, B any](o ord.Ord[K]) func(m Mo.Monoid[B]) func(func(K, A) B) func(map[K]A) B {
|
||||
return G.FoldMapOrdWithIndex[map[K]A, K, A, B](o)
|
||||
}
|
||||
|
||||
// KeysOrd returns the keys in the map in their given order
|
||||
func KeysOrd[V any, K comparable](o ord.Ord[K]) func(r map[K]V) []K {
|
||||
return G.KeysOrd[map[K]V, []K, K, V](o)
|
||||
}
|
||||
|
||||
// ValuesOrd returns the values in the map ordered by their keys in the given order
|
||||
func ValuesOrd[V any, K comparable](o ord.Ord[K]) func(r map[K]V) []V {
|
||||
return G.ValuesOrd[map[K]V, []V, K, V](o)
|
||||
}
|
||||
|
@@ -16,11 +16,14 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/IBM/fp-go/internal/utils"
|
||||
O "github.com/IBM/fp-go/option"
|
||||
S "github.com/IBM/fp-go/string"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -71,3 +74,60 @@ func TestLookup(t *testing.T) {
|
||||
assert.Equal(t, O.Some("a"), Lookup[string, string]("a")(data))
|
||||
assert.Equal(t, O.None[string](), Lookup[string, string]("a1")(data))
|
||||
}
|
||||
|
||||
func TestFilterChain(t *testing.T) {
|
||||
src := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
f := func(k string, value int) O.Option[map[string]string] {
|
||||
if value%2 != 0 {
|
||||
return O.Of(map[string]string{
|
||||
k: fmt.Sprintf("%s%d", k, value),
|
||||
})
|
||||
}
|
||||
return O.None[map[string]string]()
|
||||
}
|
||||
|
||||
// monoid
|
||||
monoid := MergeMonoid[string, string]()
|
||||
|
||||
res := FilterChainWithIndex[int](monoid)(f)(src)
|
||||
|
||||
assert.Equal(t, map[string]string{
|
||||
"a": "a1",
|
||||
"c": "c3",
|
||||
}, res)
|
||||
}
|
||||
|
||||
func ExampleFoldMap() {
|
||||
src := map[string]string{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
}
|
||||
|
||||
fold := FoldMapOrd[string, string](S.Ord)(S.Monoid)(strings.ToUpper)
|
||||
|
||||
fmt.Println(fold(src))
|
||||
|
||||
// Output: ABC
|
||||
|
||||
}
|
||||
|
||||
func ExampleValuesOrd() {
|
||||
src := map[string]string{
|
||||
"c": "a",
|
||||
"b": "b",
|
||||
"a": "c",
|
||||
}
|
||||
|
||||
getValues := ValuesOrd[string](S.Ord)
|
||||
|
||||
fmt.Println(getValues(src))
|
||||
|
||||
// Output: [c b a]
|
||||
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
// 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 record
|
||||
|
||||
import (
|
||||
@@ -22,3 +23,11 @@ import (
|
||||
func UnionSemigroup[K comparable, V any](s S.Semigroup[V]) S.Semigroup[map[K]V] {
|
||||
return G.UnionSemigroup[map[K]V](s)
|
||||
}
|
||||
|
||||
func UnionLastSemigroup[K comparable, V any]() S.Semigroup[map[K]V] {
|
||||
return G.UnionLastSemigroup[map[K]V]()
|
||||
}
|
||||
|
||||
func UnionFirstSemigroup[K comparable, V any]() S.Semigroup[map[K]V] {
|
||||
return G.UnionFirstSemigroup[map[K]V]()
|
||||
}
|
||||
|
@@ -59,3 +59,8 @@ func First[A any]() Semigroup[A] {
|
||||
func Last[A any]() Semigroup[A] {
|
||||
return MakeSemigroup(F.Second[A, A])
|
||||
}
|
||||
|
||||
// ToMagma converts a semigroup to a magma
|
||||
func ToMagma[A any](s Semigroup[A]) M.Magma[A] {
|
||||
return s
|
||||
}
|
||||
|
18
tuple/gen.go
18
tuple/gen.go
@@ -1,21 +1,7 @@
|
||||
// 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.
|
||||
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2023-07-28 22:49:18.7141124 +0200 CEST m=+0.109464201
|
||||
// 2023-08-11 11:38:30.5947727 +0200 CEST m=+0.033600301
|
||||
|
||||
package tuple
|
||||
|
||||
import (
|
||||
|
@@ -31,7 +31,7 @@ func doubleAndLog(data int) Writer[[]string, int] {
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleLoggingWriter() {
|
||||
func ExampleWriter_logging() {
|
||||
|
||||
m := A.Monoid[string]()
|
||||
s := M.ToSemigroup(m)
|
||||
|
Reference in New Issue
Block a user