**Packages**- is:exact
- base
- base-compat
- protolude
- streaming
- turtle
- rio
- base-compat-batteries
- universum
- relude
- rebase
- llvm-hs-pure
- massiv-test
- can-i-haz
- intro
- hledger-web
- tonalude
- brittany
- linear
- pretty-simple

base Control.Monad, base-compat Control.Monad.Compat, protolude Protolude Protolude.Monad, streaming Streaming, turtle Turtle, rio RIO.Prelude, base-compat-batteries Control.Monad.Compat, universum Universum.Monad.Reexport, relude Relude.Monad.Reexport, rebase Rebase.Prelude, llvm-hs-pure LLVM.Prelude, massiv-test Test.Massiv.Utils, can-i-haz Control.Monad.Except.CoHas Control.Monad.Reader.Has, intro Intro, hledger-web Hledger.Web.Import, tonalude Tonalude, brittany Language.Haskell.Brittany.Internal.Prelude

The join function is the conventional monad join operator. It
is used to remove one level of monadic structure, projecting its bound
argument into the outer level.
**Examples**

A common use of join is to run an IO computation
returned from an STM transaction, since STM transactions
can't perform IO directly. Recall that

atomically :: STM a -> IO ais used to run STM transactions atomically. So, by specializing the types of atomically and join to

atomically :: STM (IO b) -> IO (IO b) join :: IO (IO b) -> IO bwe can compose them as

join . atomically :: STM (IO b) -> IO bto run an STM transaction and the IO action it returns.

Compute the diagonal of a matrix

>>> diagonal (V2 (V2 a b) (V2 c d)) V2 a d