mirror of
https://github.com/IBM/fp-go.git
synced 2025-06-23 00:27:49 +02:00
181 lines
5.5 KiB
Go
181 lines
5.5 KiB
Go
![]() |
// 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 generic
|
||
|
|
||
|
import (
|
||
|
"time"
|
||
|
|
||
|
F "github.com/IBM/fp-go/function"
|
||
|
FI "github.com/IBM/fp-go/internal/fromio"
|
||
|
"github.com/IBM/fp-go/internal/optiont"
|
||
|
IO "github.com/IBM/fp-go/io/generic"
|
||
|
O "github.com/IBM/fp-go/option"
|
||
|
)
|
||
|
|
||
|
// type IOOption[A any] = func() Option[A]
|
||
|
|
||
|
func MakeIO[GA ~func() O.Option[A], A any](f GA) GA {
|
||
|
return f
|
||
|
}
|
||
|
|
||
|
func Of[GA ~func() O.Option[A], A any](r A) GA {
|
||
|
return MakeIO(optiont.Of(IO.MonadOf[GA, O.Option[A]], r))
|
||
|
}
|
||
|
|
||
|
func Some[GA ~func() O.Option[A], A any](r A) GA {
|
||
|
return Of[GA](r)
|
||
|
}
|
||
|
|
||
|
func None[GA ~func() O.Option[A], A any]() GA {
|
||
|
return MakeIO(optiont.None(IO.MonadOf[GA, O.Option[A]]))
|
||
|
}
|
||
|
|
||
|
func MonadOf[GA ~func() O.Option[A], A any](r A) GA {
|
||
|
return Of[GA](r)
|
||
|
}
|
||
|
|
||
|
func FromIO[GA ~func() O.Option[A], GR ~func() A, A any](mr GR) GA {
|
||
|
return MakeIO(optiont.OfF(IO.MonadMap[GR, GA, A, O.Option[A]], mr))
|
||
|
}
|
||
|
|
||
|
func FromOption[GA ~func() O.Option[A], A any](o O.Option[A]) GA {
|
||
|
return IO.Of[GA](o)
|
||
|
}
|
||
|
|
||
|
func MonadMap[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](fa GA, f func(A) B) GB {
|
||
|
return optiont.MonadMap(IO.MonadMap[GA, GB, O.Option[A], O.Option[B]], fa, f)
|
||
|
}
|
||
|
|
||
|
func Map[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) B) func(GA) GB {
|
||
|
return F.Bind2nd(MonadMap[GA, GB, A, B], f)
|
||
|
}
|
||
|
|
||
|
func MonadChain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](fa GA, f func(A) GB) GB {
|
||
|
return optiont.MonadChain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], fa, f)
|
||
|
}
|
||
|
|
||
|
func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB {
|
||
|
return F.Bind2nd(MonadChain[GA, GB, A, B], f)
|
||
|
}
|
||
|
|
||
|
func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB {
|
||
|
return optiont.MonadChainOptionK(
|
||
|
IO.MonadChain[GA, GB, O.Option[A], O.Option[B]],
|
||
|
FromOption[GB, B],
|
||
|
ma,
|
||
|
f,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func ChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) O.Option[B]) func(GA) GB {
|
||
|
return F.Bind2nd(MonadChainOptionK[GA, GB, A, B], f)
|
||
|
}
|
||
|
|
||
|
func MonadChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](ma GA, f func(A) GR) GB {
|
||
|
return FI.MonadChainIOK(
|
||
|
MonadChain[GA, GB, A, B],
|
||
|
FromIO[GB, GR, B],
|
||
|
ma,
|
||
|
f,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func ChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](f func(A) GR) func(GA) GB {
|
||
|
return FI.ChainIOK(
|
||
|
MonadChain[GA, GB, A, B],
|
||
|
FromIO[GB, GR, B],
|
||
|
f,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func MonadAp[GA ~func() O.Option[A], GB ~func() O.Option[B], GAB ~func() O.Option[func(A) B], A, B any](mab GAB, ma GA) GB {
|
||
|
return optiont.MonadAp(
|
||
|
IO.MonadAp[GA, GB, func() func(O.Option[A]) O.Option[B], O.Option[A], O.Option[B]],
|
||
|
IO.MonadMap[GAB, func() func(O.Option[A]) O.Option[B], O.Option[func(A) B], func(O.Option[A]) O.Option[B]],
|
||
|
mab, ma)
|
||
|
}
|
||
|
|
||
|
func Ap[GA ~func() O.Option[A], GB ~func() O.Option[B], GAB ~func() O.Option[func(A) B], A, B any](ma GA) func(GAB) GB {
|
||
|
return F.Bind2nd(MonadAp[GA, GB, GAB, A, B], ma)
|
||
|
}
|
||
|
|
||
|
func Flatten[GA ~func() O.Option[A], GAA ~func() O.Option[GA], A any](mma GAA) GA {
|
||
|
return MonadChain(mma, F.Identity[GA])
|
||
|
}
|
||
|
|
||
|
func Optionize0[GA ~func() O.Option[A], A any](f func() (A, bool)) func() GA {
|
||
|
ef := O.Optionize0(f)
|
||
|
return func() GA {
|
||
|
return MakeIO[GA](ef)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Optionize1[GA ~func() O.Option[A], T1, A any](f func(t1 T1) (A, bool)) func(T1) GA {
|
||
|
ef := O.Optionize1(f)
|
||
|
return func(t1 T1) GA {
|
||
|
return MakeIO[GA](func() O.Option[A] {
|
||
|
return ef(t1)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Optionize2[GA ~func() O.Option[A], T1, T2, A any](f func(t1 T1, t2 T2) (A, bool)) func(T1, T2) GA {
|
||
|
ef := O.Optionize2(f)
|
||
|
return func(t1 T1, t2 T2) GA {
|
||
|
return MakeIO[GA](func() O.Option[A] {
|
||
|
return ef(t1, t2)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Optionize3[GA ~func() O.Option[A], T1, T2, T3, A any](f func(t1 T1, t2 T2, t3 T3) (A, bool)) func(T1, T2, T3) GA {
|
||
|
ef := O.Optionize3(f)
|
||
|
return func(t1 T1, t2 T2, t3 T3) GA {
|
||
|
return MakeIO[GA](func() O.Option[A] {
|
||
|
return ef(t1, t2, t3)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Optionize4[GA ~func() O.Option[A], T1, T2, T3, T4, A any](f func(t1 T1, t2 T2, t3 T3, t4 T4) (A, bool)) func(T1, T2, T3, T4) GA {
|
||
|
ef := O.Optionize4(f)
|
||
|
return func(t1 T1, t2 T2, t3 T3, t4 T4) GA {
|
||
|
return MakeIO[GA](func() O.Option[A] {
|
||
|
return ef(t1, t2, t3, t4)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Memoize computes the value of the provided IO monad lazily but exactly once
|
||
|
func Memoize[GA ~func() O.Option[A], A any](ma GA) GA {
|
||
|
return IO.Memoize(ma)
|
||
|
}
|
||
|
|
||
|
// Delay creates an operation that passes in the value after some delay
|
||
|
func Delay[GA ~func() O.Option[A], A any](delay time.Duration) func(GA) GA {
|
||
|
return IO.Delay[GA](delay)
|
||
|
}
|
||
|
|
||
|
// Fold convers an IOOption into an IO
|
||
|
func Fold[GA ~func() O.Option[A], GB ~func() B, A, B any](onNone func() GB, onSome func(A) GB) func(GA) GB {
|
||
|
return optiont.MatchE(IO.MonadChain[GA, GB, O.Option[A], B], onNone, onSome)
|
||
|
}
|
||
|
|
||
|
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||
|
func Defer[GA ~func() O.Option[A], A any](gen func() GA) GA {
|
||
|
return IO.Defer[GA](gen)
|
||
|
}
|