Package com.jnape.palatable.lambda.monad
Class SafeT<M extends MonadRec<?,M>,A>
java.lang.Object
com.jnape.palatable.lambda.monad.SafeT<M,A>
- Type Parameters:
M
- theMonadRec
instanceA
- the carrier type
- All Implemented Interfaces:
Applicative<A,
,SafeT<M, ?>> Functor<A,
,SafeT<M, ?>> Monad<A,
,SafeT<M, ?>> MonadBase<M,
,A, SafeT<?, ?>> MonadRec<A,
,SafeT<M, ?>> MonadT<M,
A, SafeT<M, ?>, SafeT<?, ?>>
public final class SafeT<M extends MonadRec<?,M>,A>
extends Object
implements MonadT<M,A,SafeT<M,?>,SafeT<?,?>>
A stack-safe
monad transformer
that can safely interpret deeply nested left- or right-associated
binds for any MonadRec
.
Example:
Times.<Fn1<Integer, Integer>>times(100_000, f -> f.fmap(x -> x + 1), id()).apply(0); // stack-overflow
Times.<SafeT<Fn1<Integer, ?>, Integer>>times(100_000, f -> f.fmap(x -> x + 1), safeT(id()))
.<Fn1<Integer, Integer>>runSafeT()
.apply(0); // 100_000
Inspired by Phil Freeman's paper Stack Safety for Free.
-
Nested Class Summary
Nested Classes -
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptiondiscardL
(Applicative<B, SafeT<M, ?>> appB) Sequence both thisApplicative
andappB
, discarding thisApplicative's
result and returningappB
.discardR
(Applicative<B, SafeT<M, ?>> appB) Sequence both thisApplicative
andappB
, discardingappB's
result and returning thisApplicative
.Chain dependent computations that may continue or short-circuit based on previous results.Covariantly transmute this functor's parameter using the given mapping function.Given alazy
instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.pure
(B b) Lift the valueb
into this applicative functor.runSafeT()
Recover the full structure of the embeddedMonad
in a stack-safe way.trampolineM
(Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, SafeT<M, ?>>> bounce) Given some operation yielding aRecursiveResult
inside thisMonadRec
, internally trampoline the operation until it yields atermination
instruction.Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.
-
Field Details
-
body
-
pureM
-
-
Constructor Details
-
SafeT
-
-
Method Details
-
runSafeT
Recover the full structure of the embeddedMonad
in a stack-safe way.- Type Parameters:
MA
- the witnessed target type- Returns:
- the embedded
Monad
-
fmap
Covariantly transmute this functor's parameter using the given mapping function. Generally this method is specialized to return an instance of the class implementing Functor.- Specified by:
fmap
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
fmap
in interfaceFunctor<M extends MonadRec<?,
M>, A> - Specified by:
fmap
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
fmap
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
fmap
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the new parameter type- Parameters:
fn
- the mapping function- Returns:
- a functor over B (the new parameter type)
-
lift
- Specified by:
lift
in interfaceMonadBase<M extends MonadRec<?,
M>, A, SafeT<?, ?>> - Specified by:
lift
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- theMonadRec
carrier typeN
- the argumentMonadRec
witness- Parameters:
nb
- the argumentMonadRec
- Returns:
- the new
MonadBase
-
flatMap
Chain dependent computations that may continue or short-circuit based on previous results.- Specified by:
flatMap
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
flatMap
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
flatMap
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the resulting monad parameter type- Parameters:
f
- the dependent computation over A- Returns:
- the new monad instance
-
zip
Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.- Specified by:
zip
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
zip
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
zip
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
zip
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the resulting applicative parameter type- Parameters:
appFn
- the other applicative instance- Returns:
- the mapped applicative
-
lazyZip
public <B> Lazy<SafeT<M,B>> lazyZip(Lazy<? extends Applicative<Fn1<? super A, ? extends B>, SafeT<M, ?>>> lazyAppFn) Given alazy
instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports. This is useful for applicatives that support lazy evaluation and early termination.- Specified by:
lazyZip
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
lazyZip
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
lazyZip
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
lazyZip
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the resulting applicative parameter type- Parameters:
lazyAppFn
- the lazy other applicative instance- Returns:
- the mapped applicative
- See Also:
-
discardL
Sequence both thisApplicative
andappB
, discarding thisApplicative's
result and returningappB
. This is generally useful for sequentially performing side-effects.- Specified by:
discardL
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
discardL
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
discardL
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
discardL
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the type of the returned Applicative's parameter- Parameters:
appB
- the other Applicative- Returns:
- appB
-
discardR
Sequence both thisApplicative
andappB
, discardingappB's
result and returning thisApplicative
. This is generally useful for sequentially performing side-effects.- Specified by:
discardR
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
discardR
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
discardR
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
discardR
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the type of appB's parameter- Parameters:
appB
- the other Applicative- Returns:
- this Applicative
-
pure
Lift the valueb
into this applicative functor.- Specified by:
pure
in interfaceApplicative<M extends MonadRec<?,
M>, A> - Specified by:
pure
in interfaceMonad<M extends MonadRec<?,
M>, A> - Specified by:
pure
in interfaceMonadRec<M extends MonadRec<?,
M>, A> - Specified by:
pure
in interfaceMonadT<M extends MonadRec<?,
M>, A, SafeT<M extends MonadRec<?, M>, ?>, SafeT<?, ?>> - Type Parameters:
B
- the type of the returned applicative's parameter- Parameters:
b
- the value- Returns:
- an instance of this applicative over b
-
trampolineM
public <B> SafeT<M,B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, SafeT<M, ?>>> bounce) Given some operation yielding aRecursiveResult
inside thisMonadRec
, internally trampoline the operation until it yields atermination
instruction.Stack-safety depends on implementations guaranteeing that the growth of the call stack is a constant factor independent of the number of invocations of the operation. For various examples of how this can be achieved in stereotypical circumstances, see the referenced types.
-
safeT
-
pureSafeT
-
liftSafeT
-