Options
All
  • Public
  • Public/Protected
  • All
Menu

The FlatMap type class is a lightweight Monad.

It exposes flatMap, which allows to have a value in a context (F<A>) and then feed that into a function that takes a normal value and returns a value in a context (A => F<B>).

One motivation for separating this out from Monad is that there are situations where we can implement flatMap but not pure. For example, we can implement map or flatMap that transforms the values of a Map<K, ?> type, but we can't implement pure (because we wouldn't know what key to use when instantiating the new Map).

Must obey the laws defined in FlatMapLaws.

Note that having an Monad instance implies Functor and Apply implementations are also available, as FlatMap is a subtype of these.

Implementation notes

Even though in TypeScript the Funfix library is using abstract class to express type classes, when implementing this type class it is recommended that you implement it as a mixin using "implements", instead of extending it directly with "extends". See TypeScript: Mixins for details and note that we already have applyMixins defined.

Implementation example:

import {
  HK, FlatMap, Either,
  registerTypeClassInstance,
  applyMixins
} from "../src/funfix"

// Type alias defined for readability.
// HK is our encoding for higher-kinded types.
type BoxK<T> = HK<Box<any>, T>

class Box<T> implements HK<Box<any>, T> {
  constructor(public value: T) {}

  // Implements HK<Box<any>, A>, not really needed, but useful in order
  // to avoid type casts. Note they can and should be undefined:
  readonly _funKindF: Box<any>
  readonly _funKindA: T
}

class BoxFlatMap implements FlatMap<Box<any>> {
  map<A, B>(fa: BoxK<A>, f: (a: A) => B): Box<B> {
    return new Box(f((fa as Box<A>).value))
  }

  flatMap<A, B>(fa: BoxK<A>, f: (a: A) => BoxK<B>): Box<B> {
    return f((fa as Box<A>).value) as Box<B>
  }

  tailRecM<A, B>(a: A, f: (a: A) => BoxK<Either<A, B>>): Box<B> {
    let cursor = a
    while (true) {
      const box = f(cursor) as Box<Either<A, B>>
      const v = box.value
      if (v.isRight()) return new Box(v.get())
      cursor = v.swap().get()
    }
  }

  // Mixed-in, as these have default implementations
  map2: <A, B, Z>(fa: BoxK<A>, fb: BoxK<B>, f: (a: A, b: B) => Z) => Box<Z>
  ap: <A, B>(fa: BoxK<A>, ff: BoxK<(a: A) => B>) => Box<B>
  product: <A, B> (fa: BoxK<A>, fb: BoxK<B>) => Box<[A, B]>
  unit: () => Box<void>
  followedBy: <A, B>(fa: BoxK<A>, fb: BoxK<B>) => Box<B>
  followedByL: <A, B>(fa: BoxK<A>, fb: () => BoxK<B>) => Box<B>
  forEffect: <A, B>(fa: BoxK<A>, fb: BoxK<B>) => Box<A>
  forEffectL: <A, B>(fa: BoxK<A>, fb: () => BoxK<B>) => Box<A>
}

// Call needed in order to implement `map`, `map2`, `product`, etc.
// using the default implementations defined by `FlatMap`, because
// we are using `implements` instead of `extends` above and
// because in this sample we want the default implementations,
// but note that you can always provide your own
applyMixins(BoxFlatMap, [FlatMap])

// Registering global Functor instance for Box, needed in order
// for the `functorOf(Box)`, `applyOf(Box)`, `applicativeOf(Box)`
// and `flatMapOf(Box)` calls to work
registerTypeClassInstance(FlatMap)(Box, new BoxFunctor())

We are using implements in order to support multiple inheritance and to avoid inheriting any static members. In the Flow definitions (e.g. .js.flow files) for Funfix these type classes are defined with "interface", as they are meant to be interfaces that sometimes have default implementations and not classes.

Credits

This type class is inspired by the equivalent in Haskell's standard library and the implementation is inspired by the Typelevel Cats project.

Type parameters

  • F

Hierarchy

  • FlatMap

Implements

Implemented by

Index

Methods

ap

  • ap<A, B>(fa: HK<F, A>, ff: HK<F, function>): HK<F, B>
  • Inherited from Apply.ap.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • ff: HK<F, function>

    Returns HK<F, B>

flatMap

  • flatMap<A, B>(fa: HK<F, A>, f: function): HK<F, B>
  • Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • f: function
        • (a: A): HK<F, B>
        • Parameters

          • a: A

          Returns HK<F, B>

    Returns HK<F, B>

followedBy

  • followedBy<A, B>(fa: HK<F, A>, fb: HK<F, B>): HK<F, B>
  • Sequentially compose two actions, discarding any value produced by the first.

    See followedByL for a lazy version.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • fb: HK<F, B>

    Returns HK<F, B>

followedByL

  • followedByL<A, B>(fa: HK<F, A>, fb: function): HK<F, B>
  • Sequentially compose two actions, discarding any value produced by the first.

    See followedBy for the strict version.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • fb: function
        • (): HK<F, B>
        • Returns HK<F, B>

    Returns HK<F, B>

forEffect

  • forEffect<A, B>(fa: HK<F, A>, fb: HK<F, B>): HK<F, A>
  • Sequentially compose two actions, discarding any value produced by the second.

    See forEffectL for the lazy version.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • fb: HK<F, B>

    Returns HK<F, A>

forEffectL

  • forEffectL<A, B>(fa: HK<F, A>, fb: function): HK<F, A>
  • Sequentially compose two actions, discarding any value produced by the second.

    See forEffect for the strict version.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • fb: function
        • (): HK<F, B>
        • Returns HK<F, B>

    Returns HK<F, A>

map

  • map<A, B>(fa: HK<F, A>, f: function): HK<F, B>
  • Inherited from Functor.map.

    Type parameters

    • A

    • B

    Parameters

    • fa: HK<F, A>
    • f: function
        • (a: A): B
        • Parameters

          • a: A

          Returns B

    Returns HK<F, B>

map2

  • map2<A, B, Z>(fa: HK<F, A>, fb: HK<F, B>, f: function): HK<F, Z>
  • Inherited from Apply.map2.

    Type parameters

    • A

    • B

    • Z

    Parameters

    • fa: HK<F, A>
    • fb: HK<F, B>
    • f: function
        • (a: A, b: B): Z
        • Parameters

          • a: A
          • b: B

          Returns Z

    Returns HK<F, Z>

product

  • product<A, B>(fa: HK<F, A>, fb: HK<F, B>): HK<F, [A, B]>

tailRecM

  • tailRecM<A, B>(a: A, f: function): HK<F, B>
  • Keeps calling f until a Right(b) is returned.

    Based on Phil Freeman's Stack Safety for Free.

    Implementations of this method should use constant stack space relative to f.

    Type parameters

    • A

    • B

    Parameters

    • a: A
    • f: function
        • (a: A): HK<F, Either<A, B>>
        • Parameters

          • a: A

          Returns HK<F, Either<A, B>>

    Returns HK<F, B>

Legend

  • Module
  • Object literal
  • Variable
  • Function
  • Function with type parameter
  • Index signature
  • Type alias
  • Enumeration
  • Enumeration member
  • Property
  • Method
  • Interface
  • Interface with type parameter
  • Constructor
  • Property
  • Method
  • Index signature
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Method
  • Accessor
  • Index signature
  • Inherited constructor
  • Inherited property
  • Inherited method
  • Inherited accessor
  • Protected property
  • Protected method
  • Protected accessor
  • Private property
  • Private method
  • Private accessor
  • Static property
  • Static method

Generated using TypeDoc