1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00
Files
fp-go/pair/pair.go
李鑫 9c7a5bb24b fix: string format of pair.pairString() (#113)
Signed-off-by: lixin <lixin@dustess.com>
Co-authored-by: lixin <lixin@dustess.com>
2024-05-20 21:48:24 +02:00

232 lines
6.6 KiB
Go

// Copyright (c) 2024 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 pair
import (
"fmt"
F "github.com/IBM/fp-go/function"
Sg "github.com/IBM/fp-go/semigroup"
T "github.com/IBM/fp-go/tuple"
)
type (
pair struct {
h, t any
}
// Pair defines a data structure that holds two strongly typed values
Pair[A, B any] pair
)
// String prints some debug info for the object
//
// go:noinline
func pairString(s *pair) string {
return fmt.Sprintf("Pair[%T, %T](%v, %v)", s.h, s.t, s.h, s.t)
}
// Format prints some debug info for the object
//
// go:noinline
func pairFormat(e *pair, f fmt.State, c rune) {
switch c {
case 's':
fmt.Fprint(f, pairString(e))
default:
fmt.Fprint(f, pairString(e))
}
}
// String prints some debug info for the object
func (s Pair[A, B]) String() string {
return pairString((*pair)(&s))
}
// Format prints some debug info for the object
func (s Pair[A, B]) Format(f fmt.State, c rune) {
pairFormat((*pair)(&s), f, c)
}
// Of creates a [Pair] with the same value to to both fields
func Of[A any](value A) Pair[A, A] {
return Pair[A, A]{h: value, t: value}
}
// FromTuple creates a [Pair] from a [T.Tuple2]
func FromTuple[A, B any](t T.Tuple2[A, B]) Pair[A, B] {
return Pair[A, B]{h: t.F1, t: t.F2}
}
// ToTuple creates a [T.Tuple2] from a [Pair]
func ToTuple[A, B any](t Pair[A, B]) T.Tuple2[A, B] {
return T.MakeTuple2(Head(t), Tail(t))
}
// MakePair creates a [Pair] from two values
func MakePair[A, B any](a A, b B) Pair[A, B] {
return Pair[A, B]{h: a, t: b}
}
// Head returns the head value of the pair
func Head[A, B any](fa Pair[A, B]) A {
return fa.h.(A)
}
// Tail returns the head value of the pair
func Tail[A, B any](fa Pair[A, B]) B {
return fa.t.(B)
}
// MonadMapHead maps the head value
func MonadMapHead[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B] {
return Pair[A1, B]{f(Head(fa)), fa.t}
}
// MonadMap maps the head value
func MonadMap[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B] {
return MonadMapHead(fa, f)
}
// MonadMapTail maps the Tail value
func MonadMapTail[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1] {
return Pair[A, B1]{fa.h, f(Tail(fa))}
}
// MonadBiMap maps both values
func MonadBiMap[A, B, A1, B1 any](fa Pair[A, B], f func(A) A1, g func(B) B1) Pair[A1, B1] {
return Pair[A1, B1]{f(Head(fa)), g(Tail(fa))}
}
// Map maps the head value
func Map[B, A, A1 any](f func(A) A1) func(Pair[A, B]) Pair[A1, B] {
return MapHead[B, A, A1](f)
}
// MapHead maps the head value
func MapHead[B, A, A1 any](f func(A) A1) func(Pair[A, B]) Pair[A1, B] {
return F.Bind2nd(MonadMapHead[B, A, A1], f)
}
// MapTail maps the Tail value
func MapTail[A, B, B1 any](f func(B) B1) func(Pair[A, B]) Pair[A, B1] {
return F.Bind2nd(MonadMapTail[A, B, B1], f)
}
// BiMap maps both values
func BiMap[A, B, A1, B1 any](f func(A) A1, g func(B) B1) func(Pair[A, B]) Pair[A1, B1] {
return func(fa Pair[A, B]) Pair[A1, B1] {
return MonadBiMap(fa, f, g)
}
}
// MonadChainHead chains on the head value
func MonadChainHead[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B] {
fb := f(Head(fa))
return Pair[A1, B]{fb.h, sg.Concat(Tail(fa), Tail(fb))}
}
// MonadChainTail chains on the Tail value
func MonadChainTail[A, B, B1 any](sg Sg.Semigroup[A], fb Pair[A, B], f func(B) Pair[A, B1]) Pair[A, B1] {
fa := f(Tail(fb))
return Pair[A, B1]{sg.Concat(Head(fb), Head(fa)), fa.t}
}
// MonadChain chains on the head value
func MonadChain[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B] {
return MonadChainHead(sg, fa, f)
}
// ChainHead chains on the head value
func ChainHead[B, A, A1 any](sg Sg.Semigroup[B], f func(A) Pair[A1, B]) func(Pair[A, B]) Pair[A1, B] {
return func(fa Pair[A, B]) Pair[A1, B] {
return MonadChainHead(sg, fa, f)
}
}
// ChainTail chains on the Tail value
func ChainTail[A, B, B1 any](sg Sg.Semigroup[A], f func(B) Pair[A, B1]) func(Pair[A, B]) Pair[A, B1] {
return func(fa Pair[A, B]) Pair[A, B1] {
return MonadChainTail(sg, fa, f)
}
}
// Chain chains on the head value
func Chain[B, A, A1 any](sg Sg.Semigroup[B], f func(A) Pair[A1, B]) func(Pair[A, B]) Pair[A1, B] {
return ChainHead[B, A, A1](sg, f)
}
// MonadApHead applies on the head value
func MonadApHead[B, A, A1 any](sg Sg.Semigroup[B], faa Pair[func(A) A1, B], fa Pair[A, B]) Pair[A1, B] {
return Pair[A1, B]{Head(faa)(Head(fa)), sg.Concat(Tail(fa), Tail(faa))}
}
// MonadApTail applies on the Tail value
func MonadApTail[A, B, B1 any](sg Sg.Semigroup[A], fbb Pair[A, func(B) B1], fb Pair[A, B]) Pair[A, B1] {
return Pair[A, B1]{sg.Concat(Head(fb), Head(fbb)), Tail(fbb)(Tail(fb))}
}
// MonadAp applies on the head value
func MonadAp[B, A, A1 any](sg Sg.Semigroup[B], faa Pair[func(A) A1, B], fa Pair[A, B]) Pair[A1, B] {
return MonadApHead(sg, faa, fa)
}
// ApHead applies on the head value
func ApHead[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B] {
return func(faa Pair[func(A) A1, B]) Pair[A1, B] {
return MonadApHead(sg, faa, fa)
}
}
// ApTail applies on the Tail value
func ApTail[A, B, B1 any](sg Sg.Semigroup[A], fb Pair[A, B]) func(Pair[A, func(B) B1]) Pair[A, B1] {
return func(fbb Pair[A, func(B) B1]) Pair[A, B1] {
return MonadApTail(sg, fbb, fb)
}
}
// Ap applies on the head value
func Ap[B, A, A1 any](sg Sg.Semigroup[B], fa Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B] {
return ApHead[B, A, A1](sg, fa)
}
// Swap swaps the two channels
func Swap[A, B any](fa Pair[A, B]) Pair[B, A] {
return MakePair(Tail(fa), Head(fa))
}
// Paired converts a function with 2 parameters into a function taking a [Pair]
// The inverse function is [Unpaired]
func Paired[F ~func(T1, T2) R, T1, T2, R any](f F) func(Pair[T1, T2]) R {
return func(t Pair[T1, T2]) R {
return f(Head(t), Tail(t))
}
}
// Unpaired converts a function with a [Pair] parameter into a function with 2 parameters
// The inverse function is [Paired]
func Unpaired[F ~func(Pair[T1, T2]) R, T1, T2, R any](f F) func(T1, T2) R {
return func(t1 T1, t2 T2) R {
return f(MakePair(t1, t2))
}
}
func Merge[F ~func(B) func(A) R, A, B, R any](f F) func(Pair[A, B]) R {
return func(p Pair[A, B]) R {
return f(Tail(p))(Head(p))
}
}