mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-23 22:14:53 +02:00
* fix: initial checkin of v2 Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: slowly migrate IO Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: migrate MonadTraverseArray and TraverseArray Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: migrate traversal Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: complete migration of IO Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: migrate ioeither Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: refactorY Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: next step in migration Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: adjust IO generation code Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: get rid of more IO methods Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: get rid of more IO * fix: convert iooption Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: convert reader Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: convert a bit of reader Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: new build script Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: cleanup Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: reformat Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: simplify Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: some cleanup Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: adjust Pair to Haskell semantic Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: documentation and testcases Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: some performance optimizations Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: remove coverage Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> * fix: better doc Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com> --------- Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
247 lines
6.6 KiB
Go
247 lines
6.6 KiB
Go
// Copyright (c) 2023 - 2025 IBM Corp.
|
|
// All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package boolean
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestMonoidAny(t *testing.T) {
|
|
t.Run("identity element is false", func(t *testing.T) {
|
|
assert.Equal(t, false, MonoidAny.Empty())
|
|
})
|
|
|
|
t.Run("false OR false = false", func(t *testing.T) {
|
|
result := MonoidAny.Concat(false, false)
|
|
assert.Equal(t, false, result)
|
|
})
|
|
|
|
t.Run("false OR true = true", func(t *testing.T) {
|
|
result := MonoidAny.Concat(false, true)
|
|
assert.Equal(t, true, result)
|
|
})
|
|
|
|
t.Run("true OR false = true", func(t *testing.T) {
|
|
result := MonoidAny.Concat(true, false)
|
|
assert.Equal(t, true, result)
|
|
})
|
|
|
|
t.Run("true OR true = true", func(t *testing.T) {
|
|
result := MonoidAny.Concat(true, true)
|
|
assert.Equal(t, true, result)
|
|
})
|
|
|
|
t.Run("left identity: empty OR x = x", func(t *testing.T) {
|
|
assert.Equal(t, true, MonoidAny.Concat(MonoidAny.Empty(), true))
|
|
assert.Equal(t, false, MonoidAny.Concat(MonoidAny.Empty(), false))
|
|
})
|
|
|
|
t.Run("right identity: x OR empty = x", func(t *testing.T) {
|
|
assert.Equal(t, true, MonoidAny.Concat(true, MonoidAny.Empty()))
|
|
assert.Equal(t, false, MonoidAny.Concat(false, MonoidAny.Empty()))
|
|
})
|
|
|
|
t.Run("associativity: (a OR b) OR c = a OR (b OR c)", func(t *testing.T) {
|
|
a, b, c := true, false, true
|
|
left := MonoidAny.Concat(MonoidAny.Concat(a, b), c)
|
|
right := MonoidAny.Concat(a, MonoidAny.Concat(b, c))
|
|
assert.Equal(t, left, right)
|
|
})
|
|
}
|
|
|
|
func TestMonoidAll(t *testing.T) {
|
|
t.Run("identity element is true", func(t *testing.T) {
|
|
assert.Equal(t, true, MonoidAll.Empty())
|
|
})
|
|
|
|
t.Run("false AND false = false", func(t *testing.T) {
|
|
result := MonoidAll.Concat(false, false)
|
|
assert.Equal(t, false, result)
|
|
})
|
|
|
|
t.Run("false AND true = false", func(t *testing.T) {
|
|
result := MonoidAll.Concat(false, true)
|
|
assert.Equal(t, false, result)
|
|
})
|
|
|
|
t.Run("true AND false = false", func(t *testing.T) {
|
|
result := MonoidAll.Concat(true, false)
|
|
assert.Equal(t, false, result)
|
|
})
|
|
|
|
t.Run("true AND true = true", func(t *testing.T) {
|
|
result := MonoidAll.Concat(true, true)
|
|
assert.Equal(t, true, result)
|
|
})
|
|
|
|
t.Run("left identity: empty AND x = x", func(t *testing.T) {
|
|
assert.Equal(t, true, MonoidAll.Concat(MonoidAll.Empty(), true))
|
|
assert.Equal(t, false, MonoidAll.Concat(MonoidAll.Empty(), false))
|
|
})
|
|
|
|
t.Run("right identity: x AND empty = x", func(t *testing.T) {
|
|
assert.Equal(t, true, MonoidAll.Concat(true, MonoidAll.Empty()))
|
|
assert.Equal(t, false, MonoidAll.Concat(false, MonoidAll.Empty()))
|
|
})
|
|
|
|
t.Run("associativity: (a AND b) AND c = a AND (b AND c)", func(t *testing.T) {
|
|
a, b, c := true, false, true
|
|
left := MonoidAll.Concat(MonoidAll.Concat(a, b), c)
|
|
right := MonoidAll.Concat(a, MonoidAll.Concat(b, c))
|
|
assert.Equal(t, left, right)
|
|
})
|
|
}
|
|
|
|
func TestEq(t *testing.T) {
|
|
t.Run("true equals true", func(t *testing.T) {
|
|
assert.True(t, Eq.Equals(true, true))
|
|
})
|
|
|
|
t.Run("false equals false", func(t *testing.T) {
|
|
assert.True(t, Eq.Equals(false, false))
|
|
})
|
|
|
|
t.Run("true not equals false", func(t *testing.T) {
|
|
assert.False(t, Eq.Equals(true, false))
|
|
})
|
|
|
|
t.Run("false not equals true", func(t *testing.T) {
|
|
assert.False(t, Eq.Equals(false, true))
|
|
})
|
|
|
|
t.Run("reflexivity: x equals x", func(t *testing.T) {
|
|
assert.True(t, Eq.Equals(true, true))
|
|
assert.True(t, Eq.Equals(false, false))
|
|
})
|
|
|
|
t.Run("symmetry: if x equals y then y equals x", func(t *testing.T) {
|
|
assert.Equal(t, Eq.Equals(true, false), Eq.Equals(false, true))
|
|
assert.Equal(t, Eq.Equals(true, true), Eq.Equals(true, true))
|
|
})
|
|
|
|
t.Run("transitivity: if x equals y and y equals z then x equals z", func(t *testing.T) {
|
|
x, y, z := true, true, true
|
|
if Eq.Equals(x, y) && Eq.Equals(y, z) {
|
|
assert.True(t, Eq.Equals(x, z))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOrd(t *testing.T) {
|
|
t.Run("false < true", func(t *testing.T) {
|
|
result := Ord.Compare(false, true)
|
|
assert.Equal(t, -1, result)
|
|
})
|
|
|
|
t.Run("true > false", func(t *testing.T) {
|
|
result := Ord.Compare(true, false)
|
|
assert.Equal(t, 1, result)
|
|
})
|
|
|
|
t.Run("true == true", func(t *testing.T) {
|
|
result := Ord.Compare(true, true)
|
|
assert.Equal(t, 0, result)
|
|
})
|
|
|
|
t.Run("false == false", func(t *testing.T) {
|
|
result := Ord.Compare(false, false)
|
|
assert.Equal(t, 0, result)
|
|
})
|
|
|
|
t.Run("Equals method works", func(t *testing.T) {
|
|
assert.True(t, Ord.Equals(true, true))
|
|
assert.True(t, Ord.Equals(false, false))
|
|
assert.False(t, Ord.Equals(true, false))
|
|
assert.False(t, Ord.Equals(false, true))
|
|
})
|
|
|
|
t.Run("reflexivity: x <= x", func(t *testing.T) {
|
|
assert.True(t, Ord.Compare(true, true) == 0)
|
|
assert.True(t, Ord.Compare(false, false) == 0)
|
|
})
|
|
|
|
t.Run("antisymmetry: if x <= y and y <= x then x == y", func(t *testing.T) {
|
|
x, y := true, true
|
|
if Ord.Compare(x, y) <= 0 && Ord.Compare(y, x) <= 0 {
|
|
assert.Equal(t, 0, Ord.Compare(x, y))
|
|
}
|
|
})
|
|
|
|
t.Run("transitivity: if x <= y and y <= z then x <= z", func(t *testing.T) {
|
|
x, y, z := false, true, true
|
|
if Ord.Compare(x, y) <= 0 && Ord.Compare(y, z) <= 0 {
|
|
assert.True(t, Ord.Compare(x, z) <= 0)
|
|
}
|
|
})
|
|
|
|
t.Run("totality: x <= y or y <= x", func(t *testing.T) {
|
|
assert.True(t, Ord.Compare(true, false) >= 0 || Ord.Compare(false, true) >= 0)
|
|
assert.True(t, Ord.Compare(false, true) <= 0 || Ord.Compare(true, false) <= 0)
|
|
})
|
|
}
|
|
|
|
// Example tests that also serve as documentation
|
|
func ExampleMonoidAny() {
|
|
// Combine booleans with OR
|
|
result := MonoidAny.Concat(false, true)
|
|
println(result) // true
|
|
|
|
// Identity element
|
|
identity := MonoidAny.Empty()
|
|
println(identity) // false
|
|
|
|
// Output:
|
|
}
|
|
|
|
func ExampleMonoidAll() {
|
|
// Combine booleans with AND
|
|
result := MonoidAll.Concat(true, true)
|
|
println(result) // true
|
|
|
|
// Identity element
|
|
identity := MonoidAll.Empty()
|
|
println(identity) // true
|
|
|
|
// Output:
|
|
}
|
|
|
|
func ExampleEq() {
|
|
// Check equality
|
|
equal := Eq.Equals(true, true)
|
|
println(equal) // true
|
|
|
|
notEqual := Eq.Equals(true, false)
|
|
println(notEqual) // false
|
|
|
|
// Output:
|
|
}
|
|
|
|
func ExampleOrd() {
|
|
// Compare booleans (false < true)
|
|
cmp := Ord.Compare(false, true)
|
|
println(cmp) // -1
|
|
|
|
cmp2 := Ord.Compare(true, false)
|
|
println(cmp2) // 1
|
|
|
|
cmp3 := Ord.Compare(true, true)
|
|
println(cmp3) // 0
|
|
|
|
// Output:
|
|
}
|