package monadlib

  1. Overview
  2. Docs

The monad library.

Introduction

Monads in ocaml, as defined in the batteries library and lwt, are defined narrowly in terms of a type constructor, and two functions, return and bind. This misses the i abstraction, which lies in the ability to write functions that apply generally to i all monads. This library defines modules for such functions.

  • author Phil Scott
Base Modules
module type Monoid = sig ... end
module type BasePlus = sig ... end

Monads with additional monoid structure.

module type BaseLazyPlus = sig ... end

LazyPlus is another base module useful when the monad is a lazy data structure. We then allow the plus operation to be non-strict in its second argument, which makes it possible to use functions such as Monad.lsum lazily. This is what you want for lazy lists.

Library Types
module type Monad = sig ... end

Your basic library functions for monads.

module type MonadPlus = sig ... end

Library functions for monads with additional monoid structure.

module type LazyPlus = sig ... end

This is the counterpart for the lazy version of BasePlus.

module Make (M : BatInterfaces.Monad) : Monad with type 'a m = 'a M.m
module MakePlus (M : BasePlus) : MonadPlus with type 'a m = 'a M.m
module MakeLazyPlus (M : BaseLazyPlus) : LazyPlus with type 'a m = 'a M.m
module LazyM : Monad with type 'a m = 'a Lazy.t

The lazy monad. Automatically wraps calls lazily and forces as needed.

module List : MonadPlus with type 'a m = 'a list
module LazyListM : LazyPlus with type 'a m = 'a LazyList.t
module Option : MonadPlus with type 'a m = 'a option
module Continuation (T : sig ... end) : sig ... end

For the incorruptible programmer:

module Reader (T : sig ... end) : sig ... end
module Writer (M : Monoid) : sig ... end
module State (T : sig ... end) : sig ... end
module Error (E : sig ... end) : sig ... end
module type BaseCollectionM = sig ... end

Monads for collections. Stream is the current use-case for this, since it is parameterised on a collection monad (like list).

module type Stream = sig ... end

Streams supporting fair and unbounded search.

module type StreamC = sig ... end

The union of streams and collections.

Transformers
module LazyT (M : BatInterfaces.Monad) : sig ... end
module ListT (M : BatInterfaces.Monad) : sig ... end

The list monad transformer will add non-determinism to computations. I have not provided a transformer for lazy lists, since I'm not yet sure how to implement it. It would probably need a lazy version of map_m, but it's not clear to me how to write this, since whether the computations are strict will determine whether the argument has to be completely forced.

module OptionT (M : BatInterfaces.Monad) : sig ... end
module StateT (T : sig ... end) (M : BatInterfaces.Monad) : sig ... end
module WriterT (Mon : Monoid) (M : BatInterfaces.Monad) : sig ... end
Transformers on Collections

Sometimes, you might want to transform a collection monad, in such a way that functions such as BaseCollectionM.unique behave in a sensible way by regarding None as smaller than any Some. Each transformer provides a function cmp_on with which the collection functions such as BaseCollectionM.difference are implemented. We also provide the list function for transformers.

module CollectionOpt (C : BaseCollectionM) : sig ... end
module CollectionWriter (Mon : sig ... end) (C : BaseCollectionM) : sig ... end
module CollectionState (T : sig ... end) (C : BaseCollectionM) : sig ... end
module MakeStream (M : sig ... end) : sig ... end

Create a stream monad from an arbitrary inner monad, which computes the values discovered in each generation. This is pretty abstract, since we're not requiring that the inner monad is a collection. There is a constraint here, since we're strictly supposed to disallow a monad collection where order of elements matters. I think we can characterise this abstractly by saying that the plus operation on the inner monad must be commutative, but don't take my word for it!

module MakeStreamC (M : sig ... end) : sig ... end

Here, we create a stream monad from a definite collection monad Monad.BaseCollectionM. The inner monad will be used to represent the generations in the stream. The order of elements in each generation should not matter, so you might want to use a set or a bag. If you want to live life on the edge, just remember that your code should not depend on the order of elements within generations (you can, of course, depend on the order that generations appear in the stream). You can enforce this constraint by performing, say, a sort on each generation.