1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-06-23 00:27:49 +02:00
Files
fp-go/iooption/generic/iooption.go

181 lines
5.5 KiB
Go
Raw Normal View History

// 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)
}