mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-25 22:21:49 +02:00
141 lines
3.3 KiB
Go
141 lines
3.3 KiB
Go
// Copyright (c) 2024 - 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 state
|
|
|
|
import (
|
|
"github.com/IBM/fp-go/v2/function"
|
|
"github.com/IBM/fp-go/v2/internal/chain"
|
|
"github.com/IBM/fp-go/v2/internal/functor"
|
|
"github.com/IBM/fp-go/v2/pair"
|
|
)
|
|
|
|
var (
|
|
undefined any = struct{}{}
|
|
)
|
|
|
|
//go:inline
|
|
func Get[S any]() State[S, S] {
|
|
return pair.Of[S]
|
|
}
|
|
|
|
func Gets[FCT ~func(S) A, A, S any](f FCT) State[S, A] {
|
|
return func(s S) Pair[S, A] {
|
|
return pair.MakePair(s, f(s))
|
|
}
|
|
}
|
|
|
|
//go:inline
|
|
func Put[S any]() State[S, any] {
|
|
return function.Bind2nd(pair.MakePair[S, any], undefined)
|
|
}
|
|
|
|
func Modify[FCT ~func(S) S, S any](f FCT) State[S, any] {
|
|
return function.Flow2(
|
|
f,
|
|
function.Bind2nd(pair.MakePair[S, any], undefined),
|
|
)
|
|
}
|
|
|
|
//go:inline
|
|
func Of[S, A any](a A) State[S, A] {
|
|
return function.Bind2nd(pair.MakePair[S, A], a)
|
|
}
|
|
|
|
func MonadMap[S any, FCT ~func(A) B, A, B any](fa State[S, A], f FCT) State[S, B] {
|
|
return func(s S) Pair[S, B] {
|
|
p2 := fa(s)
|
|
return pair.MakePair(pair.Head(p2), f(pair.Tail(p2)))
|
|
}
|
|
}
|
|
|
|
//go:inline
|
|
func Map[S any, FCT ~func(A) B, A, B any](f FCT) Operator[S, A, B] {
|
|
return function.Bind2nd(MonadMap[S, FCT, A, B], f)
|
|
}
|
|
|
|
func MonadChain[S any, FCT ~func(A) State[S, B], A, B any](fa State[S, A], f FCT) State[S, B] {
|
|
return func(s S) Pair[S, B] {
|
|
a := fa(s)
|
|
return f(pair.Tail(a))(pair.Head(a))
|
|
}
|
|
}
|
|
|
|
//go:inline
|
|
func Chain[S any, FCT ~func(A) State[S, B], A, B any](f FCT) Operator[S, A, B] {
|
|
return function.Bind2nd(MonadChain[S, FCT, A, B], f)
|
|
}
|
|
|
|
func MonadAp[B, S, A any](fab State[S, func(A) B], fa State[S, A]) State[S, B] {
|
|
return func(s S) Pair[S, B] {
|
|
f := fab(s)
|
|
a := fa(pair.Head(f))
|
|
|
|
return pair.MakePair(pair.Head(a), pair.Tail(f)(pair.Tail(a)))
|
|
}
|
|
}
|
|
|
|
//go:inline
|
|
func Ap[B, S, A any](ga State[S, A]) Operator[S, func(A) B, B] {
|
|
return function.Bind2nd(MonadAp[B, S, A], ga)
|
|
}
|
|
|
|
func MonadChainFirst[S any, FCT ~func(A) State[S, B], A, B any](ma State[S, A], f FCT) State[S, A] {
|
|
return chain.MonadChainFirst(
|
|
MonadChain[S, func(A) State[S, A], A, A],
|
|
MonadMap[S, func(B) A],
|
|
ma,
|
|
f,
|
|
)
|
|
}
|
|
|
|
func ChainFirst[S any, FCT ~func(A) State[S, B], A, B any](f FCT) Operator[S, A, A] {
|
|
return chain.ChainFirst(
|
|
Chain[S, func(A) State[S, A], A, A],
|
|
Map[S, func(B) A],
|
|
f,
|
|
)
|
|
}
|
|
|
|
//go:inline
|
|
func Flatten[S, A any](mma State[S, State[S, A]]) State[S, A] {
|
|
return MonadChain(mma, function.Identity[State[S, A]])
|
|
}
|
|
|
|
func Execute[A, S any](s S) func(State[S, A]) S {
|
|
return func(fa State[S, A]) S {
|
|
return pair.Head(fa(s))
|
|
}
|
|
}
|
|
|
|
func Evaluate[A, S any](s S) func(State[S, A]) A {
|
|
return func(fa State[S, A]) A {
|
|
return pair.Tail(fa(s))
|
|
}
|
|
}
|
|
|
|
func MonadFlap[FAB ~func(A) B, S, A, B any](fab State[S, FAB], a A) State[S, B] {
|
|
return functor.MonadFlap(
|
|
MonadMap[S, func(FAB) B],
|
|
fab,
|
|
a)
|
|
}
|
|
|
|
func Flap[S, A, B any](a A) Operator[S, func(A) B, B] {
|
|
return functor.Flap(
|
|
Map[S, func(func(A) B) B],
|
|
a)
|
|
}
|