Class IterateT<M extends MonadRec<?,M>, A>

java.lang.Object
com.jnape.palatable.lambda.monad.transformer.builtin.IterateT<M,A>
Type Parameters:
M - the effect type
A - the element type
All Implemented Interfaces:
Applicative<A, IterateT<M,?>>, Functor<A, IterateT<M,?>>, Monad<A, IterateT<M,?>>, MonadBase<M, A, IterateT<?,?>>, MonadRec<A, IterateT<M,?>>, MonadT<M, A, IterateT<M,?>, IterateT<?,?>>

public class IterateT<M extends MonadRec<?,M>, A> extends Object implements MonadT<M, A, IterateT<M,?>, IterateT<?,?>>
A monad transformer over a co-inductive, singly-linked spine of values embedded in effects. This is analogous to Haskell's ListT (done right). All append operations (cons, snoc, etc.) are O(1) space/time complexity.

Due to its singly-linked embedded design, IterateT is a canonical example of purely-functional streaming computation. For example, to lazily print all lines from a file descriptor, an initial implementation using IterateT might take the following form:

String filePath = "/tmp/a_tale_of_two_cities.txt";
IterateT<IO<?>, String> streamLines = IterateT.unfold(
        reader -> io(() -> maybe(reader.readLine()).fmap(line -> tuple(line, reader))),
        io(() -> Files.newBufferedReader(Paths.get(filePath))));

// iterative read and print lines without retaining references
IO<Unit> printLines = streamLines.forEach(line -> io(() -> System.out.println(line)));
printLines.unsafePerformIO(); // prints "It was the best of times, it was the worst of times, [...]"
  • Method Details

    • runIterateT

      public <MMTA extends MonadRec<Maybe<Tuple2<A, IterateT<M,A>>>, M>> MMTA runIterateT()
      Recover the full structure of the embedded Monad.
      Type Parameters:
      MMTA - the witnessed target type
      Returns:
      the embedded Monad
    • runStep

      public <MStep extends MonadRec<Maybe<Tuple2<Maybe<A>, IterateT<M,A>>>, M>> MStep runStep()
      Run a single step of this IterateT, where a step is the smallest amount of work that could possibly be productive in advancing through the IterateT. Useful for implementing interleaving algorithms that require IterateTs to yield, emit, or terminate as soon as possible, regardless of whether the next element is readily available.
      Type Parameters:
      MStep - the witnessed target type of the step
      Returns:
      the step
    • cons

      public final IterateT<M,A> cons(MonadRec<A,M> head)
      Add an element inside an effect to the front of this IterateT.
      Parameters:
      head - the element
      Returns:
      the cons'ed IterateT
    • snoc

      public final IterateT<M,A> snoc(MonadRec<A,M> last)
      Add an element inside an effect to the back of this IterateT.
      Parameters:
      last - the element
      Returns:
      the snoc'ed IterateT
    • concat

      public IterateT<M,A> concat(IterateT<M,A> other)
      Concat this IterateT in front of the other IterateT.
      Parameters:
      other - the other IterateT
      Returns:
      the concatenated IterateT
    • fold

      public <B, MB extends MonadRec<B,M>> MB fold(Fn2<? super B, ? super A, ? extends MonadRec<B,M>> fn, MonadRec<B,M> acc)
      Monolithically fold the spine of this IterateT by trampolining the underlying effects (for iterative folding, use trampolineM directly).
      Type Parameters:
      B - the accumulation type
      MB - the witnessed target result type
      Parameters:
      fn - the folding function
      acc - the starting accumulation effect
      Returns:
      the folded effect result
    • foldCut

      public <B, MB extends MonadRec<B,M>> MB foldCut(Fn2<? super B, ? super A, ? extends MonadRec<RecursiveResult<B,B>, M>> fn, MonadRec<B,M> acc)
      Monolithically fold the spine of this IterateT (with the possibility of early termination) by trampolining the underlying effects (for iterative folding, use trampolineM directly).
      Type Parameters:
      B - the accumulation type
      MB - the witnessed target result type
      Parameters:
      fn - the folding function
      acc - the starting accumulation effect
      Returns:
      the folded effect result
    • forEach

      public <MU extends MonadRec<Unit,M>> MU forEach(Fn1<? super A, ? extends MonadRec<Unit,M>> fn)
      Convenience method for folding the spine of this IterateT with an action to perform on each element without accumulating any results.
      Type Parameters:
      MU - the witnessed target result type
      Parameters:
      fn - the action to perform on each element
      Returns:
      the folded effect result
    • lift

      public <B, N extends MonadRec<?,N>> IterateT<N,B> lift(MonadRec<B,N> nb)
      Lift a new argument MonadRec into this MonadBase.
      Specified by:
      lift in interface MonadBase<M extends MonadRec<?,M>, A, IterateT<?,?>>
      Specified by:
      lift in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the MonadRec carrier type
      N - the argument MonadRec witness
      Parameters:
      nb - the argument MonadRec
      Returns:
      the new MonadBase
    • trampolineM

      public <B> IterateT<M,B> trampolineM(Fn1<? super A, ? extends MonadRec<RecursiveResult<A,B>, IterateT<M,?>>> fn)
      Given some operation yielding a RecursiveResult inside this MonadRec, internally trampoline the operation until it yields a termination 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.

      Specified by:
      trampolineM in interface MonadRec<M extends MonadRec<?,M>, A>
      Type Parameters:
      B - the ultimate resulting carrier type
      Parameters:
      fn - the function to internally trampoline
      Returns:
      the trampolined MonadRec
      See Also:
    • flatMap

      public <B> IterateT<M,B> flatMap(Fn1<? super A, ? extends Monad<B, IterateT<M,?>>> f)
      Chain dependent computations that may continue or short-circuit based on previous results.
      Specified by:
      flatMap in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      flatMap in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      flatMap in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the resulting monad parameter type
      Parameters:
      f - the dependent computation over A
      Returns:
      the new monad instance
    • fmap

      public <B> IterateT<M,B> fmap(Fn1<? super A, ? extends B> fn)
      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 interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      fmap in interface Functor<M extends MonadRec<?,M>, A>
      Specified by:
      fmap in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      fmap in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      fmap in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the new parameter type
      Parameters:
      fn - the mapping function
      Returns:
      a functor over B (the new parameter type)
    • pure

      public <B> IterateT<M,B> pure(B b)
      Lift the value b into this applicative functor.
      Specified by:
      pure in interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      pure in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      pure in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      pure in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the type of the returned applicative's parameter
      Parameters:
      b - the value
      Returns:
      an instance of this applicative over b
    • toCollection

      public <C extends Collection<A>, MAS extends MonadRec<C,M>> MAS toCollection(Fn0<C> cFn0)
      Force the underlying spine of this IterateT into a Collection of type C inside the context of the monadic effect, using the provided cFn0 to construct the initial instance.

      Note that this is a fundamentally monolithic operation - meaning that incremental progress is not possible - and as such, calling this on an infinite IterateT will result in either heap exhaustion (e.g. in the case of lists) or non-termination (e.g. in the case of sets).

      Type Parameters:
      C - the Collection type
      MAS - the witnessed target type
      Parameters:
      cFn0 - the Collection construction function
      Returns:
      the List inside of the effect
    • zip

      public <B> IterateT<M,B> zip(Applicative<Fn1<? super A, ? extends B>, IterateT<M,?>> appFn)
      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 interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      zip in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      zip in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      zip in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the resulting applicative parameter type
      Parameters:
      appFn - the other applicative instance
      Returns:
      the mapped applicative
    • lazyZip

      public <B> Lazy<IterateT<M,B>> lazyZip(Lazy<? extends Applicative<Fn1<? super A, ? extends B>, IterateT<M,?>>> lazyAppFn)
      Given a lazy 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 interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      lazyZip in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      lazyZip in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      lazyZip in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the resulting applicative parameter type
      Parameters:
      lazyAppFn - the lazy other applicative instance
      Returns:
      the mapped applicative
      See Also:
    • discardL

      public <B> IterateT<M,B> discardL(Applicative<B, IterateT<M,?>> appB)
      Sequence both this Applicative and appB, discarding this Applicative's result and returning appB. This is generally useful for sequentially performing side-effects.
      Specified by:
      discardL in interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      discardL in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      discardL in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      discardL in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the type of the returned Applicative's parameter
      Parameters:
      appB - the other Applicative
      Returns:
      appB
    • discardR

      public <B> IterateT<M,A> discardR(Applicative<B, IterateT<M,?>> appB)
      Sequence both this Applicative and appB, discarding appB's result and returning this Applicative. This is generally useful for sequentially performing side-effects.
      Specified by:
      discardR in interface Applicative<M extends MonadRec<?,M>, A>
      Specified by:
      discardR in interface Monad<M extends MonadRec<?,M>, A>
      Specified by:
      discardR in interface MonadRec<M extends MonadRec<?,M>, A>
      Specified by:
      discardR in interface MonadT<M extends MonadRec<?,M>, A, IterateT<M extends MonadRec<?,M>, ?>, IterateT<?,?>>
      Type Parameters:
      B - the type of appB's parameter
      Parameters:
      appB - the other Applicative
      Returns:
      this Applicative
    • empty

      public static <M extends MonadRec<?,M>, A> IterateT<M,A> empty(Pure<M> pureM)
      Static factory method for creating an empty IterateT.
      Type Parameters:
      M - the effect type
      A - the element type
      Parameters:
      pureM - the Pure method for the effect
      Returns:
      the empty IterateT
    • singleton

      public static <M extends MonadRec<?,M>, A> IterateT<M,A> singleton(MonadRec<A,M> ma)
      Static factory method for creating an IterateT from a single element.
      Type Parameters:
      M - the effect type
      A - the element type
      Parameters:
      ma - the element
      Returns:
      the singleton IterateT
    • iterateT

      public static <M extends MonadRec<?,M>, A> IterateT<M,A> iterateT(MonadRec<Maybe<Tuple2<A, IterateT<M,A>>>, M> unwrapped)
      Static factory method for wrapping an uncons of an IterateT in an IterateT.
      Type Parameters:
      M - the effect type
      A - the element type
      Parameters:
      unwrapped - the uncons
      Returns:
      the wrapped IterateT
    • of

      @SafeVarargs public static <M extends MonadRec<?,M>, A> IterateT<M,A> of(MonadRec<A,M> ma, MonadRec<A,M>... mas)
      Static factory method for creating an IterateT from a spine represented by one or more elements.
      Type Parameters:
      M - the effect type
      A - the element type
      Parameters:
      ma - the head element
      mas - the tail elements
      Returns:
      the IterateT
    • unfold

      public static <M extends MonadRec<?,M>, A, B> IterateT<M,A> unfold(Fn1<? super B, ? extends MonadRec<Maybe<Tuple2<A,B>>, M>> fn, MonadRec<B,M> mb)
      Lazily unfold an IterateT from an unfolding function fn and a starting seed value mb by successively applying fn to the latest seed value, producing maybe a value to yield out and the next seed value for the subsequent computation.
      Type Parameters:
      M - the effect type
      A - the element type
      B - the seed type
      Parameters:
      fn - the unfolding function
      mb - the starting seed value
      Returns:
      the lazily unfolding IterateT
    • suspended

      public static <M extends MonadRec<?,M>, A> IterateT<M,A> suspended(Fn0<MonadRec<Maybe<Tuple2<A, IterateT<M,A>>>, M>> thunk, Pure<M> pureM)
      Create an IterateT from a suspended computation that yields the spine of the IterateT inside the effect.
      Type Parameters:
      M - the effect type
      A - the element type
      Parameters:
      thunk - the suspended computation
      pureM - the Pure method for the effect
      Returns:
      the IterateT
    • fromIterator

      public static <A> IterateT<IO<?>,A> fromIterator(Iterator<A> as)
      Lazily unfold an IterateT from an Iterator inside IO.
      Type Parameters:
      A - the element type
      Parameters:
      as - the Iterator
      Returns:
      the IterateT
    • pureIterateT

      public static <M extends MonadRec<?,M>> Pure<IterateT<M,?>> pureIterateT(Pure<M> pureM)
      The canonical Pure instance for IterateT.
      Type Parameters:
      M - the argument Monad witness
      Parameters:
      pureM - the argument Monad Pure
      Returns:
      the Pure instance
    • liftIterateT

      public static Lift<IterateT<?,?>> liftIterateT()
      Returns:
      the Monad lifted into IterateT