1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00

Merge pull request #26 from IBM/cleue-more-samples

fix: add array examples
This commit is contained in:
Carsten Leue
2023-08-11 22:32:26 +02:00
committed by GitHub
7 changed files with 254 additions and 0 deletions

View 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 array
import (
"fmt"
F "github.com/IBM/fp-go/function"
O "github.com/IBM/fp-go/option"
)
// Example_basic adapts examples from [https://github.com/inato/fp-ts-cheatsheet#basic-manipulation]
func Example_basic() {
someArray := From(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) // []int
isEven := func(num int) bool {
return num%2 == 0
}
square := func(num int) int {
return num * num
}
// filter and map
result := F.Pipe2(
someArray,
Filter(isEven),
Map(square),
) // [0 4 16 36 64]
// or in one go with filterMap
resultFilterMap := F.Pipe1(
someArray,
FilterMap(
F.Flow2(O.FromPredicate(isEven), O.Map(square)),
),
)
fmt.Println(result)
fmt.Println(resultFilterMap)
// Output:
// [0 4 16 36 64]
// [0 4 16 36 64]
}

View File

@@ -0,0 +1,92 @@
// 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 array
import (
"fmt"
F "github.com/IBM/fp-go/function"
I "github.com/IBM/fp-go/number/integer"
O "github.com/IBM/fp-go/option"
"github.com/IBM/fp-go/ord"
S "github.com/IBM/fp-go/string"
)
type user struct {
name string
age O.Option[int]
}
func (user user) GetName() string {
return user.name
}
func (user user) GetAge() O.Option[int] {
return user.age
}
// Example_sort adapts examples from [https://github.com/inato/fp-ts-cheatsheet#sort-elements-with-ord]
func Example_sort() {
strings := From("zyx", "abc", "klm")
sortedStrings := F.Pipe1(
strings,
Sort(S.Ord),
) // => ['abc', 'klm', 'zyx']
// reverse sort
reverseSortedStrings := F.Pipe1(
strings,
Sort(ord.Reverse(S.Ord)),
) // => ['zyx', 'klm', 'abc']
// sort Option
optionalNumbers := From(O.Some(1337), O.None[int](), O.Some(42))
sortedNums := F.Pipe1(
optionalNumbers,
Sort(O.Ord(I.Ord)),
)
// complex object with different rules
byName := F.Pipe1(
S.Ord,
ord.Contramap(user.GetName),
) // ord.Ord[user]
byAge := F.Pipe1(
O.Ord(I.Ord),
ord.Contramap(user.GetAge),
) // ord.Ord[user]
sortedUsers := F.Pipe1(
From(user{name: "a", age: O.Of(30)}, user{name: "d", age: O.Of(10)}, user{name: "c"}, user{name: "b", age: O.Of(10)}),
SortBy(From(byAge, byName)),
)
fmt.Println(sortedStrings)
fmt.Println(reverseSortedStrings)
fmt.Println(sortedNums)
fmt.Println(sortedUsers)
// Output:
// [abc klm zyx]
// [zyx klm abc]
// [None[int] Some[int](42) Some[int](1337)]
// [{c {false 0}} {b {true 10}} {d {true 10}} {a {true 30}}]
}

View File

@@ -45,3 +45,12 @@ func SortByKey[GA ~[]T, K, T any](ord O.Ord[K], f func(T) K) func(ma GA) GA {
return cpy return cpy
} }
} }
// SortBy implements a stable sort on the array given the provided ordering
func SortBy[GA ~[]T, GO ~[]O.Ord[T], T any](ord GO) func(ma GA) GA {
return F.Pipe2(
ord,
Fold[GO](O.Monoid[T]()),
Sort[GA, T],
)
}

View File

@@ -29,3 +29,8 @@ func Sort[T any](ord O.Ord[T]) func(ma []T) []T {
func SortByKey[K, T any](ord O.Ord[K], f func(T) K) func(ma []T) []T { func SortByKey[K, T any](ord O.Ord[K], f func(T) K) func(ma []T) []T {
return G.SortByKey[[]T](ord, f) return G.SortByKey[[]T](ord, f)
} }
// SortBy implements a stable sort on the array given the provided ordering
func SortBy[T any](ord []O.Ord[T]) func(ma []T) []T {
return G.SortBy[[]T, []O.Ord[T]](ord)
}

38
option/ord.go Normal file
View File

@@ -0,0 +1,38 @@
// 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 (
C "github.com/IBM/fp-go/constraints"
F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/ord"
)
// Constructs an order for [Option]
func Ord[A any](a ord.Ord[A]) ord.Ord[Option[A]] {
// some convenient shortcuts
fld := Fold(
F.Constant(Fold(F.Constant(0), F.Constant1[A](-1))),
F.Flow2(F.Curry2(a.Compare), F.Bind1st(Fold[A, int], F.Constant(1))),
)
// convert to an ordering predicate
return ord.MakeOrd(F.Uncurry2(fld), Eq(ord.ToEq(a)).Equals)
}
// FromStrictCompare constructs an [Ord] from the canonical comparison function
func FromStrictCompare[A C.Ordered]() ord.Ord[Option[A]] {
return Ord(ord.FromStrictCompare[A]())
}

46
option/ord_test.go Normal file
View 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 option
import (
"testing"
S "github.com/IBM/fp-go/string"
"github.com/stretchr/testify/assert"
)
// it('getOrd', () => {
// const OS = _.getOrd(S.Ord)
// U.deepStrictEqual(OS.compare(_.none, _.none), 0)
// U.deepStrictEqual(OS.compare(_.some('a'), _.none), 1)
// U.deepStrictEqual(OS.compare(_.none, _.some('a')), -1)
// U.deepStrictEqual(OS.compare(_.some('a'), _.some('a')), 0)
// U.deepStrictEqual(OS.compare(_.some('a'), _.some('b')), -1)
// U.deepStrictEqual(OS.compare(_.some('b'), _.some('a')), 1)
// })
func TestOrd(t *testing.T) {
os := Ord(S.Ord)
assert.Equal(t, 0, os.Compare(None[string](), None[string]()))
assert.Equal(t, 1, os.Compare(Some("a"), None[string]()))
assert.Equal(t, -1, os.Compare(None[string](), Some("a")))
assert.Equal(t, 0, os.Compare(Some("a"), Some("a")))
assert.Equal(t, -1, os.Compare(Some("a"), Some("b")))
assert.Equal(t, 1, os.Compare(Some("b"), Some("a")))
}

View File

@@ -40,6 +40,11 @@ func (self ord[T]) Compare(x, y T) int {
return self.c(x, y) return self.c(x, y)
} }
// ToEq converts an [Ord] to [E.Eq]
func ToEq[T any](o Ord[T]) E.Eq[T] {
return o
}
// MakeOrd creates an instance of an Ord // MakeOrd creates an instance of an Ord
func MakeOrd[T any](c func(x, y T) int, e func(x, y T) bool) Ord[T] { func MakeOrd[T any](c func(x, y T) int, e func(x, y T) bool) Ord[T] {
return ord[T]{c: c, e: e} return ord[T]{c: c, e: e}