mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
Add presentation to sample section (#76)
* doc: add presentation Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: add some more examples Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * doc: update presentation Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: update presentation Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: add presentation and samples Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: benchmarks Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: upload presentation Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * doc: add presentation Signed-off-by: Carsten Leue <carsten.leue@de.ibm.com> * doc: add link to video Signed-off-by: Carsten Leue <carsten.leue@de.ibm.com> --------- Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> Signed-off-by: Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -22,30 +22,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Const[E, A any] struct {
|
type Const[E, A any] struct {
|
||||||
Value E
|
value E
|
||||||
}
|
}
|
||||||
|
|
||||||
func Make[E, A any](e E) Const[E, A] {
|
func Make[E, A any](e E) Const[E, A] {
|
||||||
return Const[E, A]{Value: e}
|
return Const[E, A]{value: e}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unwrap[E, A any](c Const[E, A]) E {
|
func Unwrap[E, A any](c Const[E, A]) E {
|
||||||
return c.Value
|
return c.value
|
||||||
}
|
}
|
||||||
|
|
||||||
func Of[E, A any](m M.Monoid[E]) func(A) Const[E, A] {
|
func Of[E, A any](m M.Monoid[E]) func(A) Const[E, A] {
|
||||||
return func(a A) Const[E, A] {
|
return F.Constant1[A](Make[E, A](m.Empty()))
|
||||||
return Make[E, A](m.Empty())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMap[E, A, B any](fa Const[E, A], f func(A) B) Const[E, B] {
|
func MonadMap[E, A, B any](fa Const[E, A], f func(A) B) Const[E, B] {
|
||||||
return Make[E, B](fa.Value)
|
return Make[E, B](fa.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[E, A, B any](s S.Semigroup[E]) func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
func MonadAp[E, A, B any](s S.Semigroup[E]) func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
||||||
return func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
return func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
||||||
return Make[E, B](s.Concat(fab.Value, fa.Value))
|
return Make[E, B](s.Concat(fab.value, fa.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,12 +46,12 @@ func (s Either[E, A]) Format(f fmt.State, c rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLeft tests if the either is a left value. Rather use [Fold] if you need to access the values. Inverse is [IsRight].
|
// IsLeft tests if the [Either] is a left value. Rather use [Fold] if you need to access the values. Inverse is [IsRight].
|
||||||
func IsLeft[E, A any](val Either[E, A]) bool {
|
func IsLeft[E, A any](val Either[E, A]) bool {
|
||||||
return val.isLeft
|
return val.isLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLeft tests if the either is a right value. Rather use [Fold] if you need to access the values. Inverse is [IsLeft].
|
// IsLeft tests if the [Either] is a right value. Rather use [Fold] if you need to access the values. Inverse is [IsLeft].
|
||||||
func IsRight[E, A any](val Either[E, A]) bool {
|
func IsRight[E, A any](val Either[E, A]) bool {
|
||||||
return !val.isLeft
|
return !val.isLeft
|
||||||
}
|
}
|
||||||
|
@@ -125,10 +125,29 @@ func MonadAp[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEithe
|
|||||||
return G.MonadAp[IOEither[E, B]](mab, ma)
|
return G.MonadAp[IOEither[E, B]](mab, ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ap is an alias of [ApPar]
|
||||||
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
return G.Ap[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
return G.Ap[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadApPar[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
|
||||||
|
return G.MonadApPar[IOEither[E, B]](mab, ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApPar applies function and value in parallel
|
||||||
|
func ApPar[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
|
return G.ApPar[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadApSeq[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
|
||||||
|
return G.MonadApSeq[IOEither[E, B]](mab, ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApSeq applies function and value sequentially
|
||||||
|
func ApSeq[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
|
return G.ApSeq[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
|
}
|
||||||
|
|
||||||
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
|
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
|
||||||
return G.Flatten(mma)
|
return G.Flatten(mma)
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
G "github.com/IBM/fp-go/optics/traversal/generic"
|
G "github.com/IBM/fp-go/optics/traversal/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FromArray returns a traversal from an array for the identity monad
|
// FromArray returns a traversal from an array for the identity [Monoid]
|
||||||
func FromArray[E, A any](m M.Monoid[E]) G.Traversal[[]A, A, C.Const[E, []A], C.Const[E, A]] {
|
func FromArray[E, A any](m M.Monoid[E]) G.Traversal[[]A, A, C.Const[E, []A], C.Const[E, A]] {
|
||||||
return AR.FromArray[[]A, E, A](m)
|
return AR.FromArray[[]A, E, A](m)
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,15 @@
|
|||||||
],
|
],
|
||||||
"rangeStrategy": "bump",
|
"rangeStrategy": "bump",
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"gomod"
|
||||||
|
],
|
||||||
|
"matchDepTypes": [
|
||||||
|
"golang"
|
||||||
|
],
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": [
|
"matchUpdateTypes": [
|
||||||
"major",
|
"major",
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
This folder is meant to contain examples that illustrate how to use the library. I recommend the following reading to get an idea of the underlying concepts. These articles talk about [fp-ts](https://github.com/gcanti/fp-ts) but the concepts are very similar, only syntax differs.
|
This folder is meant to contain examples that illustrate how to use the library. I recommend the following reading to get an idea of the underlying concepts. These articles talk about [fp-ts](https://github.com/gcanti/fp-ts) but the concepts are very similar, only syntax differs.
|
||||||
|
|
||||||
|
# Video Introduction
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=Jif3jL6DRdw "introduction to fp-go")
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
|
||||||
- [Ryan's Blog](https://rlee.dev/practical-guide-to-fp-ts-part-1) - practical introduction into FP concepts
|
- [Ryan's Blog](https://rlee.dev/practical-guide-to-fp-ts-part-1) - practical introduction into FP concepts
|
||||||
|
@@ -107,6 +107,7 @@ func TestHeterogeneousHttpRequests(t *testing.T) {
|
|||||||
// BenchmarkHeterogeneousHttpRequests shows how to execute multiple HTTP requests in parallel when
|
// BenchmarkHeterogeneousHttpRequests shows how to execute multiple HTTP requests in parallel when
|
||||||
// the response structure of these requests is different. We use [R.TraverseTuple2] to account for the different types
|
// the response structure of these requests is different. We use [R.TraverseTuple2] to account for the different types
|
||||||
func BenchmarkHeterogeneousHttpRequests(b *testing.B) {
|
func BenchmarkHeterogeneousHttpRequests(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
heterogeneousHttpRequests()(context.Background())
|
heterogeneousHttpRequests()(context.Background())()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1
samples/presentation/.gitignore
vendored
Normal file
1
samples/presentation/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
~$*
|
123
samples/presentation/benchmarks/http_test.go
Normal file
123
samples/presentation/benchmarks/http_test.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
// 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 benchmarks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
HTTP "net/http"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
R "github.com/IBM/fp-go/context/readerioeither"
|
||||||
|
H "github.com/IBM/fp-go/context/readerioeither/http"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
T "github.com/IBM/fp-go/tuple"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PostItem struct {
|
||||||
|
UserId uint `json:"userId"`
|
||||||
|
Id uint `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CatFact struct {
|
||||||
|
Fact string `json:"fact"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func heterogeneousHttpRequests(count int) R.ReaderIOEither[[]T.Tuple2[PostItem, CatFact]] {
|
||||||
|
// prepare the http client
|
||||||
|
client := H.MakeClient(HTTP.DefaultClient)
|
||||||
|
// readSinglePost sends a GET request and parses the response as [PostItem]
|
||||||
|
readSinglePost := H.ReadJson[PostItem](client)
|
||||||
|
// readSingleCatFact sends a GET request and parses the response as [CatFact]
|
||||||
|
readSingleCatFact := H.ReadJson[CatFact](client)
|
||||||
|
|
||||||
|
single := F.Pipe2(
|
||||||
|
T.MakeTuple2("https://jsonplaceholder.typicode.com/posts/1", "https://catfact.ninja/fact"),
|
||||||
|
T.Map2(H.MakeGetRequest, H.MakeGetRequest),
|
||||||
|
R.TraverseTuple2(
|
||||||
|
readSinglePost,
|
||||||
|
readSingleCatFact,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return F.Pipe1(
|
||||||
|
A.Replicate(count, single),
|
||||||
|
R.SequenceArray[T.Tuple2[PostItem, CatFact]],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func heterogeneousHttpRequestsIdiomatic(count int) ([]T.Tuple2[PostItem, CatFact], error) {
|
||||||
|
// prepare the http client
|
||||||
|
var result []T.Tuple2[PostItem, CatFact]
|
||||||
|
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
resp, err := HTTP.Get("https://jsonplaceholder.typicode.com/posts/1")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var item PostItem
|
||||||
|
err = json.Unmarshal(body, &item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err = HTTP.Get("https://catfact.ninja/fact")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var fact CatFact
|
||||||
|
err = json.Unmarshal(body, &item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, T.MakeTuple2(item, fact))
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BenchmarkHeterogeneousHttpRequests shows how to execute multiple HTTP requests in parallel when
|
||||||
|
// the response structure of these requests is different. We use [R.TraverseTuple2] to account for the different types
|
||||||
|
func BenchmarkHeterogeneousHttpRequests(b *testing.B) {
|
||||||
|
|
||||||
|
count := 100
|
||||||
|
var benchResults any
|
||||||
|
|
||||||
|
b.Run("functional", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResults = heterogeneousHttpRequests(count)(context.Background())()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResults, _ = heterogeneousHttpRequestsIdiomatic(count)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalResult = benchResults
|
||||||
|
}
|
177
samples/presentation/benchmarks/map_test.go
Normal file
177
samples/presentation/benchmarks/map_test.go
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
// 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 benchmarks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
N "github.com/IBM/fp-go/number"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
createStringSet = createRandom(createRandomString(256))(256)
|
||||||
|
createIntDataSet = createRandom(randInt(10000))(256)
|
||||||
|
|
||||||
|
globalResult any
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkMap(b *testing.B) {
|
||||||
|
|
||||||
|
data := createStringSet()
|
||||||
|
|
||||||
|
var benchResult []string
|
||||||
|
|
||||||
|
b.Run("functional", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResult = F.Pipe1(
|
||||||
|
data,
|
||||||
|
A.Map(strings.ToUpper),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var result = make([]string, 0, len(data))
|
||||||
|
for _, value := range data {
|
||||||
|
result = append(result, strings.ToUpper(value))
|
||||||
|
}
|
||||||
|
benchResult = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalResult = benchResult
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEven(data int) bool {
|
||||||
|
return data%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPrime(data int) bool {
|
||||||
|
return big.NewInt(int64(data)).ProbablyPrime(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMapThenFilter(b *testing.B) {
|
||||||
|
|
||||||
|
data := createIntDataSet()
|
||||||
|
var benchResult []int
|
||||||
|
|
||||||
|
b.Run("functional isPrime", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResult = F.Pipe2(
|
||||||
|
data,
|
||||||
|
A.Filter(isPrime),
|
||||||
|
A.Map(N.Div[int](2)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic isPrime", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var result []int
|
||||||
|
for _, value := range data {
|
||||||
|
if isPrime(value) {
|
||||||
|
result = append(result, value/2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchResult = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b.Run("functional isEven", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResult = F.Pipe2(
|
||||||
|
data,
|
||||||
|
A.Filter(isEven),
|
||||||
|
A.Map(N.Div[int](2)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic isEven", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var result []int
|
||||||
|
for _, value := range data {
|
||||||
|
if isEven(value) {
|
||||||
|
result = append(result, value/2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchResult = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalResult = benchResult
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkFilterMap(b *testing.B) {
|
||||||
|
|
||||||
|
data := createIntDataSet()
|
||||||
|
var benchResult []int
|
||||||
|
|
||||||
|
b.Run("functional isPrime", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResult = F.Pipe1(
|
||||||
|
data,
|
||||||
|
A.FilterMap(F.Flow2(
|
||||||
|
O.FromPredicate(isPrime),
|
||||||
|
O.Map(N.Div[int](2)),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic isPrime", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var result []int
|
||||||
|
for _, value := range data {
|
||||||
|
if isPrime(value) {
|
||||||
|
result = append(result, value/2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchResult = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("functional isEven", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
benchResult = F.Pipe1(
|
||||||
|
data,
|
||||||
|
A.FilterMap(F.Flow2(
|
||||||
|
O.FromPredicate(isEven),
|
||||||
|
O.Map(N.Div[int](2)),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
b.Run("idiomatic isEven", func(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
|
var result []int
|
||||||
|
for _, value := range data {
|
||||||
|
if isEven(value) {
|
||||||
|
result = append(result, value/2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
benchResult = result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalResult = benchResult
|
||||||
|
}
|
59
samples/presentation/benchmarks/utils.go
Normal file
59
samples/presentation/benchmarks/utils.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// 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 benchmarks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
B "github.com/IBM/fp-go/bytes"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
|
||||||
|
var (
|
||||||
|
seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
randChar = F.Pipe2(
|
||||||
|
len(charset),
|
||||||
|
randInt,
|
||||||
|
IO.Map(charAt),
|
||||||
|
)
|
||||||
|
createRandomString = F.Flow3(
|
||||||
|
F.Bind2of2(A.Replicate[IO.IO[byte]])(randChar),
|
||||||
|
IO.SequenceArray[byte],
|
||||||
|
IO.Map(B.ToString),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func createRandom[T any](single IO.IO[T]) func(size int) IO.IO[[]T] {
|
||||||
|
return F.Flow2(
|
||||||
|
F.Bind2of2(A.Replicate[IO.IO[T]])(single),
|
||||||
|
IO.SequenceArray[T],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func charAt(idx int) byte {
|
||||||
|
return charset[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
func randInt(count int) IO.IO[int] {
|
||||||
|
return func() int {
|
||||||
|
return seededRand.Intn(count)
|
||||||
|
}
|
||||||
|
}
|
BIN
samples/presentation/cover.jpg
Normal file
BIN
samples/presentation/cover.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
1
samples/presentation/examples/data/file1.txt
Normal file
1
samples/presentation/examples/data/file1.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Some data
|
3
samples/presentation/examples/data/file2.json
Normal file
3
samples/presentation/examples/data/file2.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"a": 10
|
||||||
|
}
|
70
samples/presentation/examples/example_composition_test.go
Normal file
70
samples/presentation/examples/example_composition_test.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_composition_pipe() {
|
||||||
|
|
||||||
|
filter := func(i int) bool {
|
||||||
|
return i%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
double := func(i int) int {
|
||||||
|
return i * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
input := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
res := F.Pipe2(
|
||||||
|
input,
|
||||||
|
A.Filter(filter),
|
||||||
|
A.Map(double),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(res)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 8]
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_composition_flow() {
|
||||||
|
|
||||||
|
filter := func(i int) bool {
|
||||||
|
return i%2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
double := func(i int) int {
|
||||||
|
return i * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
input := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
filterAndDouble := F.Flow2(
|
||||||
|
A.Filter(filter),
|
||||||
|
A.Map(double),
|
||||||
|
) // func([]int) []int
|
||||||
|
|
||||||
|
fmt.Println(filterAndDouble(input))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [4 8]
|
||||||
|
}
|
103
samples/presentation/examples/example_either_test.go
Normal file
103
samples/presentation/examples/example_either_test.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
S "github.com/IBM/fp-go/string"
|
||||||
|
)
|
||||||
|
|
||||||
|
func validatePort(port int) (int, error) {
|
||||||
|
if port > 0 {
|
||||||
|
return port, nil
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("Value %d is not a valid port number", port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_either_monad() {
|
||||||
|
|
||||||
|
// func(string) E.Either[error, int]
|
||||||
|
atoi := E.Eitherize1(strconv.Atoi)
|
||||||
|
// func(int) E.Either[error, int]
|
||||||
|
valPort := E.Eitherize1(validatePort)
|
||||||
|
|
||||||
|
// func(string) E.Either[error, string]
|
||||||
|
makeUrl := F.Flow3(
|
||||||
|
atoi,
|
||||||
|
E.Chain(valPort),
|
||||||
|
E.Map[error](S.Format[int]("http://localhost:%d")),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(makeUrl("8080"))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Right[<nil>, string](http://localhost:8080)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_either_idiomatic() {
|
||||||
|
|
||||||
|
makeUrl := func(port string) (string, error) {
|
||||||
|
parsed, err := strconv.Atoi(port)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
valid, err := validatePort(parsed)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("http://localhost:%d", valid), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err := makeUrl("8080")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(url)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// http://localhost:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_either_worlds() {
|
||||||
|
|
||||||
|
// func(string) E.Either[error, int]
|
||||||
|
atoi := E.Eitherize1(strconv.Atoi)
|
||||||
|
// func(int) E.Either[error, int]
|
||||||
|
valPort := E.Eitherize1(validatePort)
|
||||||
|
|
||||||
|
// func(string) E.Either[error, string]
|
||||||
|
makeUrl := F.Flow3(
|
||||||
|
atoi,
|
||||||
|
E.Chain(valPort),
|
||||||
|
E.Map[error](S.Format[int]("http://localhost:%d")),
|
||||||
|
)
|
||||||
|
|
||||||
|
// func(string) (string, error)
|
||||||
|
makeUrlGo := E.Uneitherize1(makeUrl)
|
||||||
|
|
||||||
|
url, err := makeUrlGo("8080")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(url)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// http://localhost:8080
|
||||||
|
}
|
46
samples/presentation/examples/example_generics_test.go
Normal file
46
samples/presentation/examples/example_generics_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
N "github.com/IBM/fp-go/number"
|
||||||
|
)
|
||||||
|
|
||||||
|
// addInts adds two integers
|
||||||
|
func addInts(left, right int) int {
|
||||||
|
return left + right
|
||||||
|
}
|
||||||
|
|
||||||
|
// addNumbers adds two numbers
|
||||||
|
func addNumbers[T N.Number](left, right T) T {
|
||||||
|
return left + right
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_generics() {
|
||||||
|
// invoke the non generic version
|
||||||
|
fmt.Println(addInts(1, 2))
|
||||||
|
|
||||||
|
// invoke the generic version
|
||||||
|
fmt.Println(addNumbers(1, 2))
|
||||||
|
fmt.Println(addNumbers(1.0, 2.0))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 3
|
||||||
|
// 3
|
||||||
|
// 3
|
||||||
|
}
|
34
samples/presentation/examples/example_hof_test.go
Normal file
34
samples/presentation/examples/example_hof_test.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func captureValue[T any](captured T) func() string {
|
||||||
|
return func() string {
|
||||||
|
return fmt.Sprintf("Value: %v", captured)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_closure() {
|
||||||
|
|
||||||
|
hof := captureValue("Carsten") // func() string
|
||||||
|
|
||||||
|
fmt.Println(hof())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Value: Carsten
|
||||||
|
}
|
156
samples/presentation/examples/example_immutability_test.go
Normal file
156
samples/presentation/examples/example_immutability_test.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
N "github.com/IBM/fp-go/number"
|
||||||
|
L "github.com/IBM/fp-go/optics/lens"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Person) GetName() string {
|
||||||
|
return p.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Person) GetAge() int {
|
||||||
|
return p.age
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Person) SetName(name string) Person {
|
||||||
|
p.name = name
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Person) SetAge(age int) Person {
|
||||||
|
p.age = age
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
type Address struct {
|
||||||
|
city string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Address) GetCity() string {
|
||||||
|
return a.city
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Address) SetCity(city string) Address {
|
||||||
|
a.city = city
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
person Person
|
||||||
|
address Address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) GetPerson() Person {
|
||||||
|
return c.person
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) SetPerson(person Person) Client {
|
||||||
|
c.person = person
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) GetAddress() Address {
|
||||||
|
return c.address
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Client) SetAddress(address Address) Client {
|
||||||
|
c.address = address
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakePerson(name string, age int) Person {
|
||||||
|
return Person{name, age}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeClient(city string, name string, age int) Client {
|
||||||
|
return Client{person: Person{name, age}, address: Address{city}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_immutability_struct() {
|
||||||
|
p1 := MakePerson("Carsten", 53)
|
||||||
|
|
||||||
|
// func(int) func(Person) Person
|
||||||
|
setAge := F.Curry2(F.Swap(Person.SetAge))
|
||||||
|
|
||||||
|
p2 := F.Pipe1(
|
||||||
|
p1,
|
||||||
|
setAge(54),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(p1)
|
||||||
|
fmt.Println(p2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {Carsten 53}
|
||||||
|
// {Carsten 54}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_immutability_optics() {
|
||||||
|
|
||||||
|
// Lens[Person, int]
|
||||||
|
ageLens := L.MakeLens(Person.GetAge, Person.SetAge)
|
||||||
|
// func(Person) Person
|
||||||
|
incAge := L.Modify[Person](N.Inc[int])(ageLens)
|
||||||
|
|
||||||
|
p1 := MakePerson("Carsten", 53)
|
||||||
|
p2 := incAge(p1)
|
||||||
|
|
||||||
|
fmt.Println(p1)
|
||||||
|
fmt.Println(p2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {Carsten 53}
|
||||||
|
// {Carsten 54}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_immutability_lenses() {
|
||||||
|
|
||||||
|
// Lens[Person, string]
|
||||||
|
nameLens := L.MakeLens(Person.GetName, Person.SetName)
|
||||||
|
// Lens[Client, Person]
|
||||||
|
personLens := L.MakeLens(Client.GetPerson, Client.SetPerson)
|
||||||
|
|
||||||
|
// Lens[Client, string]
|
||||||
|
clientNameLens := F.Pipe1(
|
||||||
|
personLens,
|
||||||
|
L.Compose[Client](nameLens),
|
||||||
|
)
|
||||||
|
// func(Client) Client
|
||||||
|
upperName := L.Modify[Client](strings.ToUpper)(clientNameLens)
|
||||||
|
|
||||||
|
c1 := MakeClient("Böblingen", "Carsten", 53)
|
||||||
|
|
||||||
|
c2 := upperName(c1)
|
||||||
|
|
||||||
|
fmt.Println(c1)
|
||||||
|
fmt.Println(c2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {{Carsten 53} {Böblingen}}
|
||||||
|
// {{CARSTEN 53} {Böblingen}}
|
||||||
|
}
|
64
samples/presentation/examples/example_map_test.go
Normal file
64
samples/presentation/examples/example_map_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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
N "github.com/IBM/fp-go/number"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_map() {
|
||||||
|
|
||||||
|
f := func(i int) int {
|
||||||
|
return i * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
input := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
// idiomatic go
|
||||||
|
res1 := make([]int, 0, len(input))
|
||||||
|
for _, i := range input {
|
||||||
|
res1 = append(res1, f(i))
|
||||||
|
}
|
||||||
|
fmt.Println(res1)
|
||||||
|
|
||||||
|
// map
|
||||||
|
res2 := A.Map(f)(input)
|
||||||
|
fmt.Println(res2)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [2 4 6 8]
|
||||||
|
// [2 4 6 8]
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_reduce() {
|
||||||
|
|
||||||
|
input := []int{1, 2, 3, 4}
|
||||||
|
|
||||||
|
// reduce
|
||||||
|
red := A.Reduce(N.MonoidSum[int]().Concat, 0)(input)
|
||||||
|
fmt.Println(red)
|
||||||
|
|
||||||
|
// fold
|
||||||
|
fld := A.Fold(N.MonoidSum[int]())(input)
|
||||||
|
fmt.Println(fld)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// 10
|
||||||
|
// 10
|
||||||
|
}
|
105
samples/presentation/examples/example_sideeffect_test.go
Normal file
105
samples/presentation/examples/example_sideeffect_test.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
B "github.com/IBM/fp-go/bytes"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
|
"github.com/IBM/fp-go/ioeither/file"
|
||||||
|
J "github.com/IBM/fp-go/json"
|
||||||
|
T "github.com/IBM/fp-go/tuple"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Sample struct {
|
||||||
|
Value int `json:"a"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Sample) getValue() int {
|
||||||
|
return s.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_io_flow() {
|
||||||
|
|
||||||
|
// IOE.IOEither[error, string]
|
||||||
|
text := F.Pipe2(
|
||||||
|
"data/file1.txt",
|
||||||
|
file.ReadFile,
|
||||||
|
IOE.Map[error](B.ToString),
|
||||||
|
)
|
||||||
|
|
||||||
|
// IOE.IOEither[error, int]
|
||||||
|
value := F.Pipe3(
|
||||||
|
"data/file2.json",
|
||||||
|
file.ReadFile,
|
||||||
|
IOE.ChainEitherK(J.Unmarshal[Sample]),
|
||||||
|
IOE.Map[error](Sample.getValue),
|
||||||
|
)
|
||||||
|
|
||||||
|
// IOE.IOEither[error, string]
|
||||||
|
result := F.Pipe1(
|
||||||
|
IOE.SequenceT2(text, value),
|
||||||
|
IOE.Map[error](func(res T.Tuple2[string, int]) string {
|
||||||
|
return fmt.Sprintf("Text: %s, Number: %d", res.F1, res.F2)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(result())
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Right[<nil>, string](Text: Some data, Number: 10)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func io_flow_idiomatic() error {
|
||||||
|
|
||||||
|
// []byte
|
||||||
|
file1AsBytes, err := os.ReadFile("data/file1.txt")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// string
|
||||||
|
text := string(file1AsBytes)
|
||||||
|
|
||||||
|
// []byte
|
||||||
|
file2AsBytes, err := os.ReadFile("data/file2.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var value Sample
|
||||||
|
if err := json.Unmarshal(file2AsBytes, &value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// string
|
||||||
|
result := fmt.Sprintf("Text: %s, Number: %d", text, value.Value)
|
||||||
|
|
||||||
|
fmt.Println(result)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_io_flow_idiomatic() {
|
||||||
|
if err := io_flow_idiomatic(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Text: Some data, Number: 10
|
||||||
|
}
|
50
samples/presentation/examples/examples_monad_test.go
Normal file
50
samples/presentation/examples/examples_monad_test.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// 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 examples
|
||||||
|
|
||||||
|
type HKT[T any] struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pointed
|
||||||
|
func Of[A any](A) HKT[A] { return HKT[A]{} }
|
||||||
|
|
||||||
|
// Functor
|
||||||
|
func Map[A, B any](func(A) B) func(HKT[A]) HKT[B] { return func(HKT[A]) HKT[B] { return HKT[B]{} } }
|
||||||
|
func MapTo[A, B any](A) func(HKT[A]) HKT[B] { return func(HKT[A]) HKT[B] { return HKT[B]{} } }
|
||||||
|
|
||||||
|
// Chain
|
||||||
|
func Chain[A, B any](func(A) HKT[B]) func(HKT[A]) HKT[B] {
|
||||||
|
return func(HKT[A]) HKT[B] { return HKT[B]{} }
|
||||||
|
}
|
||||||
|
func ChainTo[A, B any](HKT[B]) func(HKT[A]) HKT[B] {
|
||||||
|
return func(HKT[A]) HKT[B] { return HKT[B]{} }
|
||||||
|
}
|
||||||
|
func ChainFirst[A, B any](func(A) HKT[B]) func(HKT[A]) HKT[A] {
|
||||||
|
return func(HKT[A]) HKT[A] { return HKT[A]{} }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply
|
||||||
|
func Ap[A, B any](HKT[A]) func(HKT[func(A) B]) HKT[B] {
|
||||||
|
return func(HKT[func(A) B]) HKT[B] { return HKT[B]{} }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derived
|
||||||
|
func Flatten[A, B any](HKT[HKT[A]]) HKT[A] {
|
||||||
|
return HKT[A]{}
|
||||||
|
}
|
||||||
|
func Reduce[A, B any](func(B, A) B, B) func(HKT[A]) HKT[B] {
|
||||||
|
return func(HKT[A]) HKT[B] { return HKT[B]{} }
|
||||||
|
}
|
BIN
samples/presentation/introduction.pptx
Normal file
BIN
samples/presentation/introduction.pptx
Normal file
Binary file not shown.
Reference in New Issue
Block a user